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
;
53 PCSRSS_CONSOLE Console
= Object
->Console
;
54 EnterCriticalSection(&Console
->Lock
);
56 if (Object
->Type
== CONIO_CONSOLE_MAGIC
)
58 // LIST_ENTRY WaitQueue;
61 * Wake-up all of the writing waiters if any, dereference them
62 * and purge them all from the list.
64 CsrNotifyWait(&Console
->ReadWaitQueue
,
68 // InitializeListHead(&WaitQueue);
70 // CsrMoveSatisfiedWait(&WaitQueue, &Console->ReadWaitQueue);
71 if (!IsListEmpty(&Console
->ReadWaitQueue
/* &WaitQueue */))
73 CsrDereferenceWait(&Console
->ReadWaitQueue
/* &WaitQueue */);
77 /* If the last handle to a screen buffer is closed, delete it... */
78 if (AdjustHandleCounts(Entry
, -1) == 0)
80 if (Object
->Type
== CONIO_SCREEN_BUFFER_MAGIC
)
82 PCSRSS_SCREEN_BUFFER Buffer
= (PCSRSS_SCREEN_BUFFER
)Object
;
83 /* ...unless it's the only buffer left. Windows allows deletion
84 * even of the last buffer, but having to deal with a lack of
85 * any active buffer might be error-prone. */
86 if (Buffer
->ListEntry
.Flink
!= Buffer
->ListEntry
.Blink
)
87 ConioDeleteScreenBuffer(Buffer
);
89 else if (Object
->Type
== CONIO_CONSOLE_MAGIC
)
91 /* TODO: FIXME: Destroy here the console ?? */
92 // ConioDeleteConsole(Console);
96 LeaveCriticalSection(&Console
->Lock
);
102 /* FUNCTIONS *****************************************************************/
106 Win32CsrInsertObject(PCONSOLE_PROCESS_DATA ProcessData
,
116 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
118 for (i
= 0; i
< ProcessData
->HandleTableSize
; i
++)
120 if (ProcessData
->HandleTable
[i
].Object
== NULL
)
125 if (i
>= ProcessData
->HandleTableSize
)
127 Block
= RtlAllocateHeap(ConSrvHeap
,
129 (ProcessData
->HandleTableSize
+ 64) * sizeof(CSRSS_HANDLE
));
132 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
133 return STATUS_UNSUCCESSFUL
;
136 ProcessData
->HandleTable
,
137 ProcessData
->HandleTableSize
* sizeof(CSRSS_HANDLE
));
138 RtlFreeHeap(ConSrvHeap
, 0, ProcessData
->HandleTable
);
139 ProcessData
->HandleTable
= Block
;
140 ProcessData
->HandleTableSize
+= 64;
142 ProcessData
->HandleTable
[i
].Object
= Object
;
143 ProcessData
->HandleTable
[i
].Access
= Access
;
144 ProcessData
->HandleTable
[i
].Inheritable
= Inheritable
;
145 ProcessData
->HandleTable
[i
].ShareMode
= ShareMode
;
146 Win32CsrCreateHandleEntry(&ProcessData
->HandleTable
[i
]);
147 *Handle
= UlongToHandle((i
<< 2) | 0x3);
148 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
149 return STATUS_SUCCESS
;
154 Win32CsrReleaseObject(PCONSOLE_PROCESS_DATA ProcessData
,
157 ULONG_PTR h
= (ULONG_PTR
)Handle
>> 2;
160 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
162 if (h
>= ProcessData
->HandleTableSize
||
163 (Object
= ProcessData
->HandleTable
[h
].Object
) == NULL
)
165 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
166 return STATUS_INVALID_HANDLE
;
168 Win32CsrCloseHandleEntry(&ProcessData
->HandleTable
[h
]);
170 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
172 return STATUS_SUCCESS
;
177 Win32CsrLockObject(PCONSOLE_PROCESS_DATA ProcessData
,
183 ULONG_PTR h
= (ULONG_PTR
)Handle
>> 2;
185 DPRINT("Win32CsrLockObject, Object: %x, %x, %x\n",
186 Object
, Handle
, ProcessData
? ProcessData
->HandleTableSize
: 0);
188 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
190 if ( !IsConsoleHandle(Handle
) ||
191 h
>= ProcessData
->HandleTableSize
||
192 (*Object
= ProcessData
->HandleTable
[h
].Object
) == NULL
||
193 ~ProcessData
->HandleTable
[h
].Access
& Access
||
194 (Type
!= 0 && (*Object
)->Type
!= Type
) )
196 DPRINT1("CsrGetObject returning invalid handle (%x)\n", Handle
);
197 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
198 return STATUS_INVALID_HANDLE
;
201 _InterlockedIncrement(&(*Object
)->Console
->ReferenceCount
);
202 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
204 EnterCriticalSection(&((*Object
)->Console
->Lock
));
205 return STATUS_SUCCESS
;
209 Win32CsrUnlockConsole(PCSRSS_CONSOLE Console
)
211 LeaveCriticalSection(&Console
->Lock
);
214 /* If it was the last held lock for the owning thread... */
215 if (&Console
->Lock
.RecursionCount
== 0)
217 /* ...dereference waiting threads if any */
218 LIST_ENTRY WaitQueue
;
219 InitializeListHead(&WaitQueue
);
221 CsrMoveSatisfiedWait(&WaitQueue
, Console
->SatisfiedWaits
);
222 Console
->SatisfiedWaits
= NULL
;
223 if (!IsListEmpty(&WaitQueue
))
225 CsrDereferenceWait(&WaitQueue
);
230 /* Decrement reference count */
231 if (_InterlockedDecrement(&Console
->ReferenceCount
) == 0)
232 ConioDeleteConsole(Console
);
237 Win32CsrUnlockObject(Object_t
*Object
)
239 Win32CsrUnlockConsole(Object
->Console
);
244 /** Remark: this function can be called by SrvAttachConsole (not yet implemented) **/
247 ConsoleNewProcess(PCSR_PROCESS SourceProcess
,
248 PCSR_PROCESS TargetProcess
)
250 /**************************************************************************
251 * This function is called whenever a new process (GUI or CUI) is created.
253 * Copy the parent's handles table here if both the parent and the child
254 * processes are CUI. If we must actually create our proper console (and
255 * thus do not inherit from the console handles of the parent's), then we
256 * will clean this table in the next ConsoleConnect call. Why we are doing
257 * this? It's because here, we still don't know whether or not we must create
258 * a new console instead of inherit it from the parent, and, because in
259 * ConsoleConnect we don't have any reference to the parent process anymore.
260 **************************************************************************/
262 PCONSOLE_PROCESS_DATA SourceProcessData
, TargetProcessData
;
265 DPRINT1("ConsoleNewProcess inside\n");
266 DPRINT1("SourceProcess = 0x%p ; TargetProcess = 0x%p\n", SourceProcess
, TargetProcess
);
268 /* An empty target process is invalid */
270 return STATUS_INVALID_PARAMETER
;
272 DPRINT1("ConsoleNewProcess - OK\n");
274 TargetProcessData
= ConsoleGetPerProcessData(TargetProcess
);
275 DPRINT1("TargetProcessData = 0x%p\n", TargetProcessData
);
277 /**** HACK !!!! ****/ RtlZeroMemory(TargetProcessData
, sizeof(*TargetProcessData
));
279 /* Initialize the new (target) process */
280 TargetProcessData
->Process
= TargetProcess
;
281 TargetProcessData
->ConsoleEvent
= NULL
;
282 TargetProcessData
->Console
= TargetProcessData
->ParentConsole
= NULL
;
283 // TargetProcessData->bInheritHandles = FALSE;
284 TargetProcessData
->ConsoleApp
= ((TargetProcess
->Flags
& CsrProcessIsConsoleApp
) ? TRUE
: FALSE
);
287 TargetProcessData
->HandleTableSize
= 0;
288 TargetProcessData
->HandleTable
= NULL
;
290 /* HACK */ RtlZeroMemory(&TargetProcessData
->HandleTableLock
, sizeof(RTL_CRITICAL_SECTION
));
291 RtlInitializeCriticalSection(&TargetProcessData
->HandleTableLock
);
293 /* Do nothing if the source process is NULL */
295 return STATUS_SUCCESS
;
297 SourceProcessData
= ConsoleGetPerProcessData(SourceProcess
);
298 DPRINT1("SourceProcessData = 0x%p\n", SourceProcessData
);
301 * If both of the processes (parent and new child) are console applications,
302 * then try to inherit handles from the parent process.
304 if ( SourceProcessData
->Console
!= NULL
&& /* SourceProcessData->ConsoleApp */
305 TargetProcessData
->ConsoleApp
)
308 if (TargetProcessData->HandleTableSize)
310 return STATUS_INVALID_PARAMETER;
314 DPRINT1("ConsoleNewProcess - Copy the handle table (1)\n");
315 /* Temporary "inherit" the console from the parent */
316 TargetProcessData
->ParentConsole
= SourceProcessData
->Console
;
317 RtlEnterCriticalSection(&SourceProcessData
->HandleTableLock
);
318 DPRINT1("ConsoleNewProcess - Copy the handle table (2)\n");
320 /* Allocate a new handle table for the child process */
321 TargetProcessData
->HandleTable
= RtlAllocateHeap(ConSrvHeap
,
323 SourceProcessData
->HandleTableSize
324 * sizeof(CSRSS_HANDLE
));
325 if (TargetProcessData
->HandleTable
== NULL
)
327 RtlLeaveCriticalSection(&SourceProcessData
->HandleTableLock
);
328 return STATUS_UNSUCCESSFUL
;
331 TargetProcessData
->HandleTableSize
= SourceProcessData
->HandleTableSize
;
334 * Parse the parent process' handles table and, for each handle,
335 * do a copy of it and reference it, if the handle is inheritable.
337 for (i
= 0; i
< SourceProcessData
->HandleTableSize
; i
++)
339 if (SourceProcessData
->HandleTable
[i
].Object
!= NULL
&&
340 SourceProcessData
->HandleTable
[i
].Inheritable
)
343 * Copy the handle data and increment the reference count of the
344 * pointed object (via the call to Win32CsrCreateHandleEntry).
346 TargetProcessData
->HandleTable
[i
] = SourceProcessData
->HandleTable
[i
];
347 Win32CsrCreateHandleEntry(&TargetProcessData
->HandleTable
[i
]);
351 RtlLeaveCriticalSection(&SourceProcessData
->HandleTableLock
);
355 DPRINT1("ConsoleNewProcess - We don't launch a Console process : SourceProcessData->Console = 0x%p ; TargetProcess->Flags = %lu\n", SourceProcessData
->Console
, TargetProcess
->Flags
);
358 return STATUS_SUCCESS
;
361 // Temporary ; move it to a header.
362 NTSTATUS WINAPI
CsrInitConsole(PCSRSS_CONSOLE
* NewConsole
, int ShowCmd
);
366 ConsoleConnect(IN PCSR_PROCESS CsrProcess
,
367 IN OUT PVOID ConnectionInfo
,
368 IN OUT PULONG ConnectionInfoLength
)
370 /**************************************************************************
371 * This function is called whenever a CUI new process is created.
372 **************************************************************************/
374 NTSTATUS Status
= STATUS_SUCCESS
;
375 PCONSOLE_CONNECTION_INFO ConnectInfo
= (PCONSOLE_CONNECTION_INFO
)ConnectionInfo
;
376 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrProcess
);
377 BOOLEAN NewConsole
= FALSE
;
378 // PCSRSS_CONSOLE Console = NULL;
380 DPRINT1("ConsoleConnect\n");
382 if ( ConnectionInfo
== NULL
||
383 ConnectionInfoLength
== NULL
||
384 *ConnectionInfoLength
!= sizeof(CONSOLE_CONNECTION_INFO
) )
386 DPRINT1("CONSRV: Connection failed\n");
387 return STATUS_UNSUCCESSFUL
;
390 /* If we don't need a console, then get out of here */
391 if (!ConnectInfo
->ConsoleNeeded
|| !ProcessData
->ConsoleApp
) // In fact, it is for GUI apps.
393 DPRINT("ConsoleConnect - No console needed\n");
394 return STATUS_SUCCESS
;
397 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
399 /* If we don't have a console, then create a new one... */
400 if (!ConnectInfo
->Console
||
401 ConnectInfo
->Console
!= ProcessData
->ParentConsole
)
403 // PCSRSS_CONSOLE Console;
405 DPRINT1("ConsoleConnect - Allocate a new console\n");
407 /* Initialize a new Console */
409 Status
= CsrInitConsole(&ProcessData
->Console
, ConnectInfo
->ShowCmd
);
410 if (!NT_SUCCESS(Status
))
412 DPRINT1("Console initialization failed\n");
413 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
417 else /* We inherit it from the parent */
419 DPRINT1("ConsoleConnect - Reuse current (parent's) console\n");
421 /* Reuse our current console */
423 ProcessData
->Console
= ConnectInfo
->Console
;
426 /* Insert the process into the processes list of the console */
427 InsertHeadList(&ProcessData
->Console
->ProcessList
, &ProcessData
->ConsoleLink
);
429 /* Return it to the caller */
430 ConnectInfo
->Console
= ProcessData
->Console
;
432 /* Add a reference count because the process is tied to the console */
433 _InterlockedIncrement(&ProcessData
->Console
->ReferenceCount
);
435 if (NewConsole
/* || !ProcessData->bInheritHandles */)
438 * We've just created a new console. However when ConsoleNewProcess was
439 * called, we didn't know that we wanted to create a new console and
440 * therefore, we by default inherited the handles table from our parent
441 * process. It's only now that we notice that in fact we do not need
442 * them, because we've created a new console and thus we must use it.
444 * Therefore, free our handles table and recreate a new one.
449 /* Close all console handles and free the handle table memory */
450 for (i
= 0; i
< ProcessData
->HandleTableSize
; i
++)
452 Win32CsrCloseHandleEntry(&ProcessData
->HandleTable
[i
]);
454 ProcessData
->HandleTableSize
= 0;
455 RtlFreeHeap(ConSrvHeap
, 0, ProcessData
->HandleTable
);
456 ProcessData
->HandleTable
= NULL
;
459 * Create a new handle table - Insert the IO handles
462 /* Insert the Input handle */
463 Status
= Win32CsrInsertObject(ProcessData
,
464 &ConnectInfo
->InputHandle
,
465 &ProcessData
->Console
->Header
,
466 GENERIC_READ
| GENERIC_WRITE
,
468 FILE_SHARE_READ
| FILE_SHARE_WRITE
);
469 if (!NT_SUCCESS(Status
))
471 DPRINT1("Failed to insert the input handle\n");
472 ConioDeleteConsole(ProcessData
->Console
);
473 ProcessData
->Console
= NULL
;
474 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
478 /* Insert the Output handle */
479 Status
= Win32CsrInsertObject(ProcessData
,
480 &ConnectInfo
->OutputHandle
,
481 &ProcessData
->Console
->ActiveBuffer
->Header
,
482 GENERIC_READ
| GENERIC_WRITE
,
484 FILE_SHARE_READ
| FILE_SHARE_WRITE
);
485 if (!NT_SUCCESS(Status
))
487 DPRINT1("Failed to insert the output handle\n");
488 ConioDeleteConsole(ProcessData
->Console
);
489 Win32CsrReleaseObject(ProcessData
,
490 ConnectInfo
->InputHandle
);
491 ProcessData
->Console
= NULL
;
492 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
496 /* Insert the Error handle */
497 Status
= Win32CsrInsertObject(ProcessData
,
498 &ConnectInfo
->ErrorHandle
,
499 &ProcessData
->Console
->ActiveBuffer
->Header
,
500 GENERIC_READ
| GENERIC_WRITE
,
502 FILE_SHARE_READ
| FILE_SHARE_WRITE
);
503 if (!NT_SUCCESS(Status
))
505 DPRINT1("Failed to insert the error handle\n");
506 ConioDeleteConsole(ProcessData
->Console
);
507 Win32CsrReleaseObject(ProcessData
,
508 ConnectInfo
->OutputHandle
);
509 Win32CsrReleaseObject(ProcessData
,
510 ConnectInfo
->InputHandle
);
511 ProcessData
->Console
= NULL
;
512 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
517 /* Duplicate the Event */
518 Status
= NtDuplicateObject(NtCurrentProcess(),
519 ProcessData
->Console
->ActiveEvent
,
520 ProcessData
->Process
->ProcessHandle
,
521 &ProcessData
->ConsoleEvent
,
522 EVENT_ALL_ACCESS
, 0, 0);
523 if (!NT_SUCCESS(Status
))
525 DPRINT1("NtDuplicateObject() failed: %lu\n", Status
);
526 ConioDeleteConsole(ProcessData
->Console
);
527 if (NewConsole
/* || !ProcessData->bInheritHandles */)
529 Win32CsrReleaseObject(ProcessData
,
530 ConnectInfo
->ErrorHandle
);
531 Win32CsrReleaseObject(ProcessData
,
532 ConnectInfo
->OutputHandle
);
533 Win32CsrReleaseObject(ProcessData
,
534 ConnectInfo
->InputHandle
);
536 ProcessData
->Console
= NULL
;
537 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
540 /* Input Wait Handle */
541 ConnectInfo
->InputWaitHandle
= ProcessData
->ConsoleEvent
;
543 /* Set the Ctrl Dispatcher */
544 ProcessData
->CtrlDispatcher
= ConnectInfo
->CtrlDispatcher
;
545 DPRINT("CSRSS:CtrlDispatcher address: %x\n", ProcessData
->CtrlDispatcher
);
547 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
548 return STATUS_SUCCESS
;
553 Win32CsrReleaseConsole(PCSR_PROCESS Process
)
555 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(Process
);
556 PCSRSS_CONSOLE Console
;
559 DPRINT1("Win32CsrReleaseConsole\n");
561 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
563 /* Close all console handles and free the handle table memory */
564 for (i
= 0; i
< ProcessData
->HandleTableSize
; i
++)
566 Win32CsrCloseHandleEntry(&ProcessData
->HandleTable
[i
]);
568 ProcessData
->HandleTableSize
= 0;
569 RtlFreeHeap(ConSrvHeap
, 0, ProcessData
->HandleTable
);
570 ProcessData
->HandleTable
= NULL
;
572 /* Detach process from console */
573 Console
= ProcessData
->Console
;
576 DPRINT1("Win32CsrReleaseConsole - Console->ReferenceCount = %lu - We are going to decrement it !\n", Console
->ReferenceCount
);
577 ProcessData
->Console
= NULL
;
578 EnterCriticalSection(&Console
->Lock
);
579 RemoveEntryList(&ProcessData
->ConsoleLink
);
580 Win32CsrUnlockConsole(Console
);
581 //CloseHandle(ProcessData->ConsoleEvent);
582 //ProcessData->ConsoleEvent = NULL;
585 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
590 ConsoleDisconnect(PCSR_PROCESS Process
)
592 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(Process
);
594 /**************************************************************************
595 * This function is called whenever a new process (GUI or CUI) is destroyed.
597 * Only do something if the process is a CUI. <-- modify this behaviour if
598 * we deal with a GUI which
599 * quits and acquired a
601 **************************************************************************/
603 DPRINT1("ConsoleDisconnect called\n");
604 // if (ProcessData->Console != NULL)
605 if (ProcessData
->ConsoleApp
)
607 DPRINT1("ConsoleDisconnect - calling Win32CsrReleaseConsole\n");
608 Win32CsrReleaseConsole(Process
);
611 RtlDeleteCriticalSection(&ProcessData
->HandleTableLock
);
616 CSR_API(SrvCloseHandle
)
618 PCSRSS_CLOSE_HANDLE CloseHandleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.CloseHandleRequest
;
620 return Win32CsrReleaseObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
621 CloseHandleRequest
->Handle
);
624 CSR_API(SrvVerifyConsoleIoHandle
)
626 NTSTATUS Status
= STATUS_SUCCESS
;
627 PCSRSS_VERIFY_HANDLE VerifyHandleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.VerifyHandleRequest
;
628 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
629 HANDLE Handle
= VerifyHandleRequest
->Handle
;
630 ULONG_PTR Index
= (ULONG_PTR
)Handle
>> 2;
632 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
634 if (!IsConsoleHandle(Handle
) ||
635 Index
>= ProcessData
->HandleTableSize
||
636 ProcessData
->HandleTable
[Index
].Object
== NULL
)
638 DPRINT("CsrVerifyObject failed\n");
639 Status
= STATUS_INVALID_HANDLE
;
642 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
647 CSR_API(SrvDuplicateHandle
)
651 PCSRSS_DUPLICATE_HANDLE DuplicateHandleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.DuplicateHandleRequest
;
652 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
653 HANDLE Handle
= DuplicateHandleRequest
->Handle
;
654 ULONG_PTR Index
= (ULONG_PTR
)Handle
>> 2;
656 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
658 if ( /** !IsConsoleHandle(Handle) || **/
659 Index
>= ProcessData
->HandleTableSize
||
660 (Entry
= &ProcessData
->HandleTable
[Index
])->Object
== NULL
)
662 DPRINT1("Couldn't duplicate invalid handle %p\n", Handle
);
663 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
664 return STATUS_INVALID_HANDLE
;
667 if (DuplicateHandleRequest
->Options
& DUPLICATE_SAME_ACCESS
)
669 DesiredAccess
= Entry
->Access
;
673 DesiredAccess
= DuplicateHandleRequest
->Access
;
674 /* Make sure the source handle has all the desired flags */
675 if (~Entry
->Access
& DesiredAccess
)
677 DPRINT1("Handle %p only has access %X; requested %X\n",
678 Handle
, Entry
->Access
, DesiredAccess
);
679 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
680 return STATUS_INVALID_PARAMETER
;
684 ApiMessage
->Status
= Win32CsrInsertObject(ProcessData
,
685 &DuplicateHandleRequest
->Handle
, // Use the new handle value!
688 DuplicateHandleRequest
->Inheritable
,
690 if (NT_SUCCESS(ApiMessage
->Status
) &&
691 DuplicateHandleRequest
->Options
& DUPLICATE_CLOSE_SOURCE
)
693 Win32CsrCloseHandleEntry(Entry
);
696 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
697 return ApiMessage
->Status
;
701 CSR_API(CsrGetInputWaitHandle)
703 PCSRSS_GET_INPUT_WAIT_HANDLE GetConsoleInputWaitHandle = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetConsoleInputWaitHandle;
705 GetConsoleInputWaitHandle->InputWaitHandle =
706 ConsoleGetPerProcessData(CsrGetClientThread()->Process)->ConsoleEvent;
708 return STATUS_SUCCESS;