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
6 * PROGRAMMERS: David Welch
8 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
11 /* INCLUDES *******************************************************************/
14 #include "include/conio.h"
17 #include "include/console.h"
19 #include "conoutput.h"
25 /* GLOBALS ********************************************************************/
27 typedef struct _CONSOLE_IO_HANDLE
29 PCONSOLE_IO_OBJECT Object
; /* The object on which the handle points to */
33 } CONSOLE_IO_HANDLE
, *PCONSOLE_IO_HANDLE
;
36 /* PRIVATE FUNCTIONS **********************************************************/
39 AdjustHandleCounts(PCONSOLE_IO_HANDLE Entry
, INT Change
)
41 PCONSOLE_IO_OBJECT Object
= Entry
->Object
;
43 DPRINT("AdjustHandleCounts(0x%p, %d), Object = 0x%p\n", Entry
, Change
, Object
);
44 DPRINT("\tAdjustHandleCounts(0x%p, %d), Object = 0x%p, Object->HandleCount = %d, Object->Type = %lu\n", Entry
, Change
, Object
, Object
->HandleCount
, Object
->Type
);
46 if (Entry
->Access
& GENERIC_READ
) Object
->AccessRead
+= Change
;
47 if (Entry
->Access
& GENERIC_WRITE
) Object
->AccessWrite
+= Change
;
48 if (!(Entry
->ShareMode
& FILE_SHARE_READ
)) Object
->ExclusiveRead
+= Change
;
49 if (!(Entry
->ShareMode
& FILE_SHARE_WRITE
)) Object
->ExclusiveWrite
+= Change
;
51 Object
->HandleCount
+= Change
;
53 return Object
->HandleCount
;
57 ConSrvCreateHandleEntry(PCONSOLE_IO_HANDLE Entry
)
59 /// LOCK /// PCONSOLE_IO_OBJECT Object = Entry->Object;
60 /// LOCK /// EnterCriticalSection(&Object->Console->Lock);
61 AdjustHandleCounts(Entry
, +1);
62 /// LOCK /// LeaveCriticalSection(&Object->Console->Lock);
66 ConSrvCloseHandleEntry(PCONSOLE_IO_HANDLE Entry
)
68 PCONSOLE_IO_OBJECT Object
= Entry
->Object
;
71 /// LOCK /// PCONSOLE Console = Object->Console;
72 /// LOCK /// EnterCriticalSection(&Console->Lock);
75 * If this is a input handle, notify and dereference
76 * all the waits related to this handle.
78 if (Object
->Type
== INPUT_BUFFER
)
80 PCONSOLE_INPUT_BUFFER InputBuffer
= (PCONSOLE_INPUT_BUFFER
)Object
;
83 * Wake up all the writing waiters related to this handle for this
84 * input buffer, if any, then dereference them and purge them all
86 * To select them amongst all the waiters for this input buffer,
87 * pass the handle pointer to the waiters, then they will check
88 * whether or not they are related to this handle and if so, they
91 CsrNotifyWait(&InputBuffer
->ReadWaitQueue
,
95 if (!IsListEmpty(&InputBuffer
->ReadWaitQueue
))
97 CsrDereferenceWait(&InputBuffer
->ReadWaitQueue
);
101 /* If the last handle to a screen buffer is closed, delete it... */
102 if (AdjustHandleCounts(Entry
, -1) == 0)
104 if (Object
->Type
== TEXTMODE_BUFFER
|| Object
->Type
== GRAPHICS_BUFFER
)
106 PCONSOLE_SCREEN_BUFFER Buffer
= (PCONSOLE_SCREEN_BUFFER
)Object
;
107 /* ...unless it's the only buffer left. Windows allows deletion
108 * even of the last buffer, but having to deal with a lack of
109 * any active buffer might be error-prone. */
110 if (Buffer
->ListEntry
.Flink
!= Buffer
->ListEntry
.Blink
)
111 ConioDeleteScreenBuffer(Buffer
);
113 else if (Object
->Type
== INPUT_BUFFER
)
115 DPRINT("Closing the input buffer\n");
119 DPRINT1("Invalid object type %d\n", Object
->Type
);
123 /// LOCK /// LeaveCriticalSection(&Console->Lock);
125 /* Invalidate (zero-out) this handle entry */
126 // Entry->Object = NULL;
127 // RtlZeroMemory(Entry, sizeof(*Entry));
129 RtlZeroMemory(Entry
, sizeof(*Entry
)); // Be sure the whole entry is invalidated.
133 /* Forward declaration, used in ConSrvInitHandlesTable */
134 static VOID
ConSrvFreeHandlesTable(PCONSOLE_PROCESS_DATA ProcessData
);
137 ConSrvInitHandlesTable(IN OUT PCONSOLE_PROCESS_DATA ProcessData
,
138 OUT PHANDLE pInputHandle
,
139 OUT PHANDLE pOutputHandle
,
140 OUT PHANDLE pErrorHandle
)
143 HANDLE InputHandle
= INVALID_HANDLE_VALUE
,
144 OutputHandle
= INVALID_HANDLE_VALUE
,
145 ErrorHandle
= INVALID_HANDLE_VALUE
;
148 * Initialize the handles table. Use temporary variables to store
149 * the handles values in such a way that, if we fail, we don't
150 * return to the caller invalid handle values.
152 * Insert the IO handles.
155 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
157 /* Insert the Input handle */
158 Status
= ConSrvInsertObject(ProcessData
,
160 &ProcessData
->Console
->InputBuffer
.Header
,
161 GENERIC_READ
| GENERIC_WRITE
,
163 FILE_SHARE_READ
| FILE_SHARE_WRITE
);
164 if (!NT_SUCCESS(Status
))
166 DPRINT1("Failed to insert the input handle\n");
167 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
168 ConSrvFreeHandlesTable(ProcessData
);
172 /* Insert the Output handle */
173 Status
= ConSrvInsertObject(ProcessData
,
175 &ProcessData
->Console
->ActiveBuffer
->Header
,
176 GENERIC_READ
| GENERIC_WRITE
,
178 FILE_SHARE_READ
| FILE_SHARE_WRITE
);
179 if (!NT_SUCCESS(Status
))
181 DPRINT1("Failed to insert the output handle\n");
182 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
183 ConSrvFreeHandlesTable(ProcessData
);
187 /* Insert the Error handle */
188 Status
= ConSrvInsertObject(ProcessData
,
190 &ProcessData
->Console
->ActiveBuffer
->Header
,
191 GENERIC_READ
| GENERIC_WRITE
,
193 FILE_SHARE_READ
| FILE_SHARE_WRITE
);
194 if (!NT_SUCCESS(Status
))
196 DPRINT1("Failed to insert the error handle\n");
197 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
198 ConSrvFreeHandlesTable(ProcessData
);
202 /* Return the newly created handles */
203 *pInputHandle
= InputHandle
;
204 *pOutputHandle
= OutputHandle
;
205 *pErrorHandle
= ErrorHandle
;
207 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
208 return STATUS_SUCCESS
;
212 ConSrvInheritHandlesTable(IN PCONSOLE_PROCESS_DATA SourceProcessData
,
213 IN PCONSOLE_PROCESS_DATA TargetProcessData
)
215 NTSTATUS Status
= STATUS_SUCCESS
;
218 RtlEnterCriticalSection(&SourceProcessData
->HandleTableLock
);
220 /* Inherit a handles table only if there is no already */
221 if (TargetProcessData
->HandleTable
!= NULL
/* || TargetProcessData->HandleTableSize != 0 */)
223 Status
= STATUS_UNSUCCESSFUL
;
227 /* Allocate a new handle table for the child process */
228 TargetProcessData
->HandleTable
= ConsoleAllocHeap(HEAP_ZERO_MEMORY
,
229 SourceProcessData
->HandleTableSize
230 * sizeof(CONSOLE_IO_HANDLE
));
231 if (TargetProcessData
->HandleTable
== NULL
)
233 Status
= STATUS_NO_MEMORY
;
237 TargetProcessData
->HandleTableSize
= SourceProcessData
->HandleTableSize
;
240 * Parse the parent process' handles table and, for each handle,
241 * do a copy of it and reference it, if the handle is inheritable.
243 for (i
= 0, j
= 0; i
< SourceProcessData
->HandleTableSize
; i
++)
245 if (SourceProcessData
->HandleTable
[i
].Object
!= NULL
&&
246 SourceProcessData
->HandleTable
[i
].Inheritable
)
249 * Copy the handle data and increment the reference count of the
250 * pointed object (via the call to ConSrvCreateHandleEntry).
252 TargetProcessData
->HandleTable
[j
] = SourceProcessData
->HandleTable
[i
];
253 ConSrvCreateHandleEntry(&TargetProcessData
->HandleTable
[j
]);
259 RtlLeaveCriticalSection(&SourceProcessData
->HandleTableLock
);
264 ConSrvFreeHandlesTable(PCONSOLE_PROCESS_DATA ProcessData
)
266 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
268 if (ProcessData
->HandleTable
!= NULL
)
273 * ProcessData->Console is NULL (and the assertion fails) when
274 * ConSrvFreeHandlesTable is called in ConSrvConnect during the
275 * allocation of a new console.
277 // ASSERT(ProcessData->Console);
278 if (ProcessData
->Console
!= NULL
)
280 /* Close all the console handles */
281 for (i
= 0; i
< ProcessData
->HandleTableSize
; i
++)
283 ConSrvCloseHandleEntry(&ProcessData
->HandleTable
[i
]);
286 /* Free the handles table memory */
287 ConsoleFreeHeap(ProcessData
->HandleTable
);
288 ProcessData
->HandleTable
= NULL
;
291 ProcessData
->HandleTableSize
= 0;
293 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
298 ConSrvInitObject(IN OUT PCONSOLE_IO_OBJECT Object
,
299 IN CONSOLE_IO_OBJECT_TYPE Type
,
303 // if (!Object) return;
306 Object
->Console
= Console
;
307 Object
->AccessRead
= Object
->AccessWrite
= 0;
308 Object
->ExclusiveRead
= Object
->ExclusiveWrite
= 0;
309 Object
->HandleCount
= 0;
314 ConSrvInsertObject(PCONSOLE_PROCESS_DATA ProcessData
,
316 PCONSOLE_IO_OBJECT Object
,
321 #define IO_HANDLES_INCREMENT 2 * 3
324 PCONSOLE_IO_HANDLE Block
;
326 // NOTE: Commented out because calling code always lock HandleTableLock before.
327 // RtlEnterCriticalSection(&ProcessData->HandleTableLock);
329 ASSERT( (ProcessData
->HandleTable
== NULL
&& ProcessData
->HandleTableSize
== 0) ||
330 (ProcessData
->HandleTable
!= NULL
&& ProcessData
->HandleTableSize
!= 0) );
332 if (ProcessData
->HandleTable
)
334 for (i
= 0; i
< ProcessData
->HandleTableSize
; i
++)
336 if (ProcessData
->HandleTable
[i
].Object
== NULL
)
341 if (i
>= ProcessData
->HandleTableSize
)
343 /* Allocate a new handles table */
344 Block
= ConsoleAllocHeap(HEAP_ZERO_MEMORY
,
345 (ProcessData
->HandleTableSize
+
346 IO_HANDLES_INCREMENT
) * sizeof(CONSOLE_IO_HANDLE
));
349 // RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
350 return STATUS_UNSUCCESSFUL
;
353 /* If we previously had a handles table, free it and use the new one */
354 if (ProcessData
->HandleTable
)
356 /* Copy the handles from the old table to the new one */
358 ProcessData
->HandleTable
,
359 ProcessData
->HandleTableSize
* sizeof(CONSOLE_IO_HANDLE
));
360 ConsoleFreeHeap(ProcessData
->HandleTable
);
362 ProcessData
->HandleTable
= Block
;
363 ProcessData
->HandleTableSize
+= IO_HANDLES_INCREMENT
;
366 ProcessData
->HandleTable
[i
].Object
= Object
;
367 ProcessData
->HandleTable
[i
].Access
= Access
;
368 ProcessData
->HandleTable
[i
].Inheritable
= Inheritable
;
369 ProcessData
->HandleTable
[i
].ShareMode
= ShareMode
;
370 ConSrvCreateHandleEntry(&ProcessData
->HandleTable
[i
]);
371 *Handle
= ULongToHandle((i
<< 2) | 0x3);
373 // RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
375 return STATUS_SUCCESS
;
380 ConSrvRemoveObject(PCONSOLE_PROCESS_DATA ProcessData
,
383 ULONG_PTR h
= (ULONG_PTR
)Handle
>> 2;
384 PCONSOLE_IO_OBJECT Object
;
386 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
388 ASSERT(ProcessData
->HandleTable
);
390 if (h
>= ProcessData
->HandleTableSize
||
391 (Object
= ProcessData
->HandleTable
[h
].Object
) == NULL
)
393 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
394 return STATUS_INVALID_HANDLE
;
397 ASSERT(ProcessData
->Console
);
398 ConSrvCloseHandleEntry(&ProcessData
->HandleTable
[h
]);
400 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
401 return STATUS_SUCCESS
;
406 ConSrvGetObject(PCONSOLE_PROCESS_DATA ProcessData
,
408 PCONSOLE_IO_OBJECT
* Object
,
409 PVOID
* Entry OPTIONAL
,
412 CONSOLE_IO_OBJECT_TYPE Type
)
414 ULONG_PTR h
= (ULONG_PTR
)Handle
>> 2;
415 PCONSOLE_IO_HANDLE HandleEntry
= NULL
;
416 PCONSOLE_IO_OBJECT ObjectEntry
= NULL
;
419 if (Entry
) *Entry
= NULL
;
421 // DPRINT("ConSrvGetObject, Object: %x, %x, %x\n",
422 // Object, Handle, ProcessData ? ProcessData->HandleTableSize : 0);
424 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
426 if ( IsConsoleHandle(Handle
) &&
427 h
< ProcessData
->HandleTableSize
)
429 HandleEntry
= &ProcessData
->HandleTable
[h
];
430 ObjectEntry
= HandleEntry
->Object
;
433 if ( HandleEntry
== NULL
||
434 ObjectEntry
== NULL
||
435 (HandleEntry
->Access
& Access
) == 0 ||
436 /*(Type != 0 && ObjectEntry->Type != Type)*/
437 (Type
!= 0 && (ObjectEntry
->Type
& Type
) == 0) )
439 DPRINT1("ConSrvGetObject returning invalid handle (%x) of type %lu with access %lu ; wanted type %lu with access %lu\n", Handle
, ObjectEntry
->Type
, HandleEntry
->Access
, Type
, Access
);
440 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
441 return STATUS_INVALID_HANDLE
;
444 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
446 if (ConSrvValidateConsole(ObjectEntry
->Console
, CONSOLE_RUNNING
, LockConsole
))
448 _InterlockedIncrement(&ObjectEntry
->Console
->ReferenceCount
);
450 /* Return the objects to the caller */
451 *Object
= ObjectEntry
;
452 if (Entry
) *Entry
= HandleEntry
;
454 // RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
455 return STATUS_SUCCESS
;
459 // RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
460 return STATUS_INVALID_HANDLE
;
466 ConSrvReleaseObject(PCONSOLE_IO_OBJECT Object
,
467 BOOL IsConsoleLocked
)
469 ConSrvReleaseConsole(Object
->Console
, IsConsoleLocked
);
474 ConSrvAllocateConsole(PCONSOLE_PROCESS_DATA ProcessData
,
475 PHANDLE pInputHandle
,
476 PHANDLE pOutputHandle
,
477 PHANDLE pErrorHandle
,
478 PCONSOLE_START_INFO ConsoleStartInfo
)
480 NTSTATUS Status
= STATUS_SUCCESS
;
483 * We are about to create a new console. However when ConSrvNewProcess
484 * was called, we didn't know that we wanted to create a new console and
485 * therefore, we by default inherited the handles table from our parent
486 * process. It's only now that we notice that in fact we do not need
487 * them, because we've created a new console and thus we must use it.
489 * Therefore, free the handles table so that we can recreate
490 * a new one later on.
492 ConSrvFreeHandlesTable(ProcessData
);
494 /* Initialize a new Console owned by this process */
495 Status
= ConSrvInitConsole(&ProcessData
->Console
, ConsoleStartInfo
, ProcessData
->Process
);
496 if (!NT_SUCCESS(Status
))
498 DPRINT1("Console initialization failed\n");
502 /* Initialize the handles table */
503 Status
= ConSrvInitHandlesTable(ProcessData
,
507 if (!NT_SUCCESS(Status
))
509 DPRINT1("Failed to initialize the handles table\n");
510 ConSrvDeleteConsole(ProcessData
->Console
);
511 ProcessData
->Console
= NULL
;
515 /* Duplicate the Input Event */
516 Status
= NtDuplicateObject(NtCurrentProcess(),
517 ProcessData
->Console
->InputBuffer
.ActiveEvent
,
518 ProcessData
->Process
->ProcessHandle
,
519 &ProcessData
->ConsoleEvent
,
520 EVENT_ALL_ACCESS
, 0, 0);
521 if (!NT_SUCCESS(Status
))
523 DPRINT1("NtDuplicateObject() failed: %lu\n", Status
);
524 ConSrvFreeHandlesTable(ProcessData
);
525 ConSrvDeleteConsole(ProcessData
->Console
);
526 ProcessData
->Console
= NULL
;
530 /* Insert the process into the processes list of the console */
531 InsertHeadList(&ProcessData
->Console
->ProcessList
, &ProcessData
->ConsoleLink
);
533 /* Add a reference count because the process is tied to the console */
534 _InterlockedIncrement(&ProcessData
->Console
->ReferenceCount
);
536 /* Update the internal info of the terminal */
537 ConioRefreshInternalInfo(ProcessData
->Console
);
539 return STATUS_SUCCESS
;
544 ConSrvInheritConsole(PCONSOLE_PROCESS_DATA ProcessData
,
546 BOOL CreateNewHandlesTable
,
547 PHANDLE pInputHandle
,
548 PHANDLE pOutputHandle
,
549 PHANDLE pErrorHandle
)
551 NTSTATUS Status
= STATUS_SUCCESS
;
553 /* Validate and lock the console */
554 if (!ConSrvValidateConsole(Console
, CONSOLE_RUNNING
, TRUE
))
556 // FIXME: Find another status code
557 return STATUS_UNSUCCESSFUL
;
560 /* Inherit the console */
561 ProcessData
->Console
= Console
;
563 if (CreateNewHandlesTable
)
566 * We are about to create a new console. However when ConSrvNewProcess
567 * was called, we didn't know that we wanted to create a new console and
568 * therefore, we by default inherited the handles table from our parent
569 * process. It's only now that we notice that in fact we do not need
570 * them, because we've created a new console and thus we must use it.
572 * Therefore, free the handles table so that we can recreate
573 * a new one later on.
575 ConSrvFreeHandlesTable(ProcessData
);
577 /* Initialize the handles table */
578 Status
= ConSrvInitHandlesTable(ProcessData
,
582 if (!NT_SUCCESS(Status
))
584 DPRINT1("Failed to initialize the handles table\n");
585 ProcessData
->Console
= NULL
;
590 /* Duplicate the Input Event */
591 Status
= NtDuplicateObject(NtCurrentProcess(),
592 ProcessData
->Console
->InputBuffer
.ActiveEvent
,
593 ProcessData
->Process
->ProcessHandle
,
594 &ProcessData
->ConsoleEvent
,
595 EVENT_ALL_ACCESS
, 0, 0);
596 if (!NT_SUCCESS(Status
))
598 DPRINT1("NtDuplicateObject() failed: %lu\n", Status
);
599 ConSrvFreeHandlesTable(ProcessData
); // NOTE: Always free the handles table.
600 ProcessData
->Console
= NULL
;
604 /* Insert the process into the processes list of the console */
605 InsertHeadList(&ProcessData
->Console
->ProcessList
, &ProcessData
->ConsoleLink
);
607 /* Add a reference count because the process is tied to the console */
608 _InterlockedIncrement(&ProcessData
->Console
->ReferenceCount
);
610 /* Update the internal info of the terminal */
611 ConioRefreshInternalInfo(ProcessData
->Console
);
613 Status
= STATUS_SUCCESS
;
616 /* Unlock the console and return */
617 LeaveCriticalSection(&Console
->Lock
);
623 ConSrvRemoveConsole(PCONSOLE_PROCESS_DATA ProcessData
)
625 PCONSOLE Console
= ProcessData
->Console
;
627 DPRINT("ConSrvRemoveConsole\n");
629 // RtlEnterCriticalSection(&ProcessData->HandleTableLock);
631 /* Validate and lock the console */
632 if (ConSrvValidateConsole(Console
, CONSOLE_RUNNING
, TRUE
))
634 DPRINT("ConSrvRemoveConsole - Locking OK\n");
636 /* Close all console handles and free the handles table */
637 ConSrvFreeHandlesTable(ProcessData
);
639 /* Detach the process from the console */
640 ProcessData
->Console
= NULL
;
642 /* Remove ourselves from the console's list of processes */
643 RemoveEntryList(&ProcessData
->ConsoleLink
);
645 /* Update the internal info of the terminal */
646 ConioRefreshInternalInfo(Console
);
648 /* Release the console */
649 DPRINT("ConSrvRemoveConsole - Decrement Console->ReferenceCount = %lu\n", Console
->ReferenceCount
);
650 ConSrvReleaseConsole(Console
, TRUE
);
651 //CloseHandle(ProcessData->ConsoleEvent);
652 //ProcessData->ConsoleEvent = NULL;
655 // RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
659 /* PUBLIC SERVER APIS *********************************************************/
661 CSR_API(SrvOpenConsole
)
664 * This API opens a handle to either the input buffer or to
665 * a screen-buffer of the console of the current process.
669 PCONSOLE_OPENCONSOLE OpenConsoleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.OpenConsoleRequest
;
670 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
673 DWORD DesiredAccess
= OpenConsoleRequest
->Access
;
674 DWORD ShareMode
= OpenConsoleRequest
->ShareMode
;
675 PCONSOLE_IO_OBJECT Object
;
677 OpenConsoleRequest
->ConsoleHandle
= INVALID_HANDLE_VALUE
;
679 Status
= ConSrvGetConsole(ProcessData
, &Console
, TRUE
);
680 if (!NT_SUCCESS(Status
))
682 DPRINT1("Can't get console\n");
686 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
689 * Open a handle to either the active screen buffer or the input buffer.
691 if (OpenConsoleRequest
->HandleType
== HANDLE_OUTPUT
)
693 Object
= &Console
->ActiveBuffer
->Header
;
697 Object
= &Console
->InputBuffer
.Header
;
700 if (((DesiredAccess
& GENERIC_READ
) && Object
->ExclusiveRead
!= 0) ||
701 ((DesiredAccess
& GENERIC_WRITE
) && Object
->ExclusiveWrite
!= 0) ||
702 (!(ShareMode
& FILE_SHARE_READ
) && Object
->AccessRead
!= 0) ||
703 (!(ShareMode
& FILE_SHARE_WRITE
) && Object
->AccessWrite
!= 0))
705 DPRINT1("Sharing violation\n");
706 Status
= STATUS_SHARING_VIOLATION
;
710 Status
= ConSrvInsertObject(ProcessData
,
711 &OpenConsoleRequest
->ConsoleHandle
,
714 OpenConsoleRequest
->Inheritable
,
718 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
720 ConSrvReleaseConsole(Console
, TRUE
);
724 CSR_API(SrvCloseHandle
)
727 PCONSOLE_CLOSEHANDLE CloseHandleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.CloseHandleRequest
;
728 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
731 Status
= ConSrvGetConsole(ProcessData
, &Console
, TRUE
);
732 if (!NT_SUCCESS(Status
))
734 DPRINT1("Can't get console\n");
738 Status
= ConSrvRemoveObject(ProcessData
, CloseHandleRequest
->ConsoleHandle
);
740 ConSrvReleaseConsole(Console
, TRUE
);
744 CSR_API(SrvVerifyConsoleIoHandle
)
747 PCONSOLE_VERIFYHANDLE VerifyHandleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.VerifyHandleRequest
;
748 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
751 HANDLE ConsoleHandle
= VerifyHandleRequest
->ConsoleHandle
;
752 ULONG_PTR Index
= (ULONG_PTR
)ConsoleHandle
>> 2;
754 Status
= ConSrvGetConsole(ProcessData
, &Console
, TRUE
);
755 if (!NT_SUCCESS(Status
))
757 DPRINT1("Can't get console\n");
761 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
763 if (!IsConsoleHandle(ConsoleHandle
) ||
764 Index
>= ProcessData
->HandleTableSize
||
765 ProcessData
->HandleTable
[Index
].Object
== NULL
)
767 DPRINT("SrvVerifyConsoleIoHandle failed\n");
768 Status
= STATUS_INVALID_HANDLE
;
771 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
773 ConSrvReleaseConsole(Console
, TRUE
);
777 CSR_API(SrvDuplicateHandle
)
780 PCONSOLE_DUPLICATEHANDLE DuplicateHandleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.DuplicateHandleRequest
;
781 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
784 HANDLE ConsoleHandle
= DuplicateHandleRequest
->ConsoleHandle
;
785 ULONG_PTR Index
= (ULONG_PTR
)ConsoleHandle
>> 2;
786 PCONSOLE_IO_HANDLE Entry
;
789 Status
= ConSrvGetConsole(ProcessData
, &Console
, TRUE
);
790 if (!NT_SUCCESS(Status
))
792 DPRINT1("Can't get console\n");
796 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
798 if ( /** !IsConsoleHandle(ConsoleHandle) || **/
799 Index
>= ProcessData
->HandleTableSize
||
800 (Entry
= &ProcessData
->HandleTable
[Index
])->Object
== NULL
)
802 DPRINT1("Couldn't duplicate invalid handle %p\n", ConsoleHandle
);
803 Status
= STATUS_INVALID_HANDLE
;
807 if (DuplicateHandleRequest
->Options
& DUPLICATE_SAME_ACCESS
)
809 DesiredAccess
= Entry
->Access
;
813 DesiredAccess
= DuplicateHandleRequest
->Access
;
814 /* Make sure the source handle has all the desired flags */
815 if ((Entry
->Access
& DesiredAccess
) == 0)
817 DPRINT1("Handle %p only has access %X; requested %X\n",
818 ConsoleHandle
, Entry
->Access
, DesiredAccess
);
819 Status
= STATUS_INVALID_PARAMETER
;
824 /* Insert the new handle inside the process handles table */
825 Status
= ConSrvInsertObject(ProcessData
,
826 &DuplicateHandleRequest
->ConsoleHandle
, // Use the new handle value!
829 DuplicateHandleRequest
->Inheritable
,
831 if (NT_SUCCESS(Status
) &&
832 (DuplicateHandleRequest
->Options
& DUPLICATE_CLOSE_SOURCE
))
834 /* Close the original handle if needed */
835 ConSrvCloseHandleEntry(Entry
);
839 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
841 ConSrvReleaseConsole(Console
, TRUE
);