2 * LICENSE: GPL - See COPYING in the top level directory
3 * PROJECT: ReactOS Console Server DLL
4 * FILE: win32ss/user/winsrv/consrv/handle.c
5 * PURPOSE: Console I/O Handles functions
6 * PROGRAMMERS: David Welch
8 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
11 /* INCLUDES *******************************************************************/
15 #include <win/console.h>
20 /* GLOBALS ********************************************************************/
22 typedef struct _CONSOLE_IO_HANDLE
24 PCONSOLE_IO_OBJECT Object
; /* The object on which the handle points to */
28 } CONSOLE_IO_HANDLE
, *PCONSOLE_IO_HANDLE
;
31 /* PRIVATE FUNCTIONS **********************************************************/
34 AdjustHandleCounts(PCONSOLE_IO_HANDLE Entry
, INT Change
)
36 PCONSOLE_IO_OBJECT Object
= Entry
->Object
;
38 DPRINT("AdjustHandleCounts(0x%p, %d), Object = 0x%p\n", Entry
, Change
, Object
);
39 DPRINT("\tAdjustHandleCounts(0x%p, %d), Object = 0x%p, Object->HandleCount = %d, Object->Type = %lu\n", Entry
, Change
, Object
, Object
->HandleCount
, Object
->Type
);
41 if (Entry
->Access
& GENERIC_READ
) Object
->AccessRead
+= Change
;
42 if (Entry
->Access
& GENERIC_WRITE
) Object
->AccessWrite
+= Change
;
43 if (!(Entry
->ShareMode
& FILE_SHARE_READ
)) Object
->ExclusiveRead
+= Change
;
44 if (!(Entry
->ShareMode
& FILE_SHARE_WRITE
)) Object
->ExclusiveWrite
+= Change
;
46 Object
->HandleCount
+= Change
;
48 return Object
->HandleCount
;
52 ConSrvCreateHandleEntry(PCONSOLE_IO_HANDLE Entry
)
54 /// LOCK /// PCONSOLE_IO_OBJECT Object = Entry->Object;
55 /// LOCK /// EnterCriticalSection(&Object->Console->Lock);
56 AdjustHandleCounts(Entry
, +1);
57 /// LOCK /// LeaveCriticalSection(&Object->Console->Lock);
61 ConSrvCloseHandleEntry(PCONSOLE_IO_HANDLE Entry
)
63 PCONSOLE_IO_OBJECT Object
= Entry
->Object
;
66 /// LOCK /// PCONSOLE Console = Object->Console;
67 /// LOCK /// EnterCriticalSection(&Console->Lock);
70 * If this is a input handle, notify and dereference
71 * all the waits related to this handle.
73 if (Object
->Type
== INPUT_BUFFER
)
75 PCONSOLE_INPUT_BUFFER InputBuffer
= (PCONSOLE_INPUT_BUFFER
)Object
;
78 * Wake up all the writing waiters related to this handle for this
79 * input buffer, if any, then dereference them and purge them all
81 * To select them amongst all the waiters for this input buffer,
82 * pass the handle pointer to the waiters, then they will check
83 * whether or not they are related to this handle and if so, they
86 CsrNotifyWait(&InputBuffer
->ReadWaitQueue
,
90 if (!IsListEmpty(&InputBuffer
->ReadWaitQueue
))
92 CsrDereferenceWait(&InputBuffer
->ReadWaitQueue
);
96 /* If the last handle to a screen buffer is closed, delete it... */
97 if (AdjustHandleCounts(Entry
, -1) == 0)
99 if (Object
->Type
== TEXTMODE_BUFFER
|| Object
->Type
== GRAPHICS_BUFFER
)
101 PCONSOLE_SCREEN_BUFFER Buffer
= (PCONSOLE_SCREEN_BUFFER
)Object
;
102 /* ...unless it's the only buffer left. Windows allows deletion
103 * even of the last buffer, but having to deal with a lack of
104 * any active buffer might be error-prone. */
105 if (Buffer
->ListEntry
.Flink
!= Buffer
->ListEntry
.Blink
)
106 ConioDeleteScreenBuffer(Buffer
);
108 else if (Object
->Type
== INPUT_BUFFER
)
110 DPRINT("Closing the input buffer\n");
114 DPRINT1("Invalid object type %d\n", Object
->Type
);
118 /// LOCK /// LeaveCriticalSection(&Console->Lock);
120 /* Invalidate (zero-out) this handle entry */
121 // Entry->Object = NULL;
122 // RtlZeroMemory(Entry, sizeof(*Entry));
124 RtlZeroMemory(Entry
, sizeof(*Entry
)); // Be sure the whole entry is invalidated.
128 /* Forward declaration, used in ConSrvInitHandlesTable */
129 static VOID
ConSrvFreeHandlesTable(PCONSOLE_PROCESS_DATA ProcessData
);
132 ConSrvInitHandlesTable(IN OUT PCONSOLE_PROCESS_DATA ProcessData
,
134 OUT PHANDLE pInputHandle
,
135 OUT PHANDLE pOutputHandle
,
136 OUT PHANDLE pErrorHandle
)
139 HANDLE InputHandle
= INVALID_HANDLE_VALUE
,
140 OutputHandle
= INVALID_HANDLE_VALUE
,
141 ErrorHandle
= INVALID_HANDLE_VALUE
;
144 * Initialize the handles table. Use temporary variables to store
145 * the handles values in such a way that, if we fail, we don't
146 * return to the caller invalid handle values.
148 * Insert the IO handles.
151 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
153 /* Insert the Input handle */
154 Status
= ConSrvInsertObject(ProcessData
,
156 &Console
->InputBuffer
.Header
,
157 GENERIC_READ
| GENERIC_WRITE
,
159 FILE_SHARE_READ
| FILE_SHARE_WRITE
);
160 if (!NT_SUCCESS(Status
))
162 DPRINT1("Failed to insert the input handle\n");
163 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
164 ConSrvFreeHandlesTable(ProcessData
);
168 /* Insert the Output handle */
169 Status
= ConSrvInsertObject(ProcessData
,
171 &Console
->ActiveBuffer
->Header
,
172 GENERIC_READ
| GENERIC_WRITE
,
174 FILE_SHARE_READ
| FILE_SHARE_WRITE
);
175 if (!NT_SUCCESS(Status
))
177 DPRINT1("Failed to insert the output handle\n");
178 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
179 ConSrvFreeHandlesTable(ProcessData
);
183 /* Insert the Error handle */
184 Status
= ConSrvInsertObject(ProcessData
,
186 &Console
->ActiveBuffer
->Header
,
187 GENERIC_READ
| GENERIC_WRITE
,
189 FILE_SHARE_READ
| FILE_SHARE_WRITE
);
190 if (!NT_SUCCESS(Status
))
192 DPRINT1("Failed to insert the error handle\n");
193 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
194 ConSrvFreeHandlesTable(ProcessData
);
198 /* Return the newly created handles */
199 *pInputHandle
= InputHandle
;
200 *pOutputHandle
= OutputHandle
;
201 *pErrorHandle
= ErrorHandle
;
203 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
204 return STATUS_SUCCESS
;
208 ConSrvInheritHandlesTable(IN PCONSOLE_PROCESS_DATA SourceProcessData
,
209 IN PCONSOLE_PROCESS_DATA TargetProcessData
)
211 NTSTATUS Status
= STATUS_SUCCESS
;
214 RtlEnterCriticalSection(&SourceProcessData
->HandleTableLock
);
216 /* Inherit a handles table only if there is no already */
217 if (TargetProcessData
->HandleTable
!= NULL
/* || TargetProcessData->HandleTableSize != 0 */)
219 Status
= STATUS_UNSUCCESSFUL
;
223 /* Allocate a new handle table for the child process */
224 TargetProcessData
->HandleTable
= ConsoleAllocHeap(HEAP_ZERO_MEMORY
,
225 SourceProcessData
->HandleTableSize
226 * sizeof(CONSOLE_IO_HANDLE
));
227 if (TargetProcessData
->HandleTable
== NULL
)
229 Status
= STATUS_NO_MEMORY
;
233 TargetProcessData
->HandleTableSize
= SourceProcessData
->HandleTableSize
;
236 * Parse the parent process' handles table and, for each handle,
237 * do a copy of it and reference it, if the handle is inheritable.
239 for (i
= 0, j
= 0; i
< SourceProcessData
->HandleTableSize
; i
++)
241 if (SourceProcessData
->HandleTable
[i
].Object
!= NULL
&&
242 SourceProcessData
->HandleTable
[i
].Inheritable
)
245 * Copy the handle data and increment the reference count of the
246 * pointed object (via the call to ConSrvCreateHandleEntry).
248 TargetProcessData
->HandleTable
[j
] = SourceProcessData
->HandleTable
[i
];
249 ConSrvCreateHandleEntry(&TargetProcessData
->HandleTable
[j
]);
255 RtlLeaveCriticalSection(&SourceProcessData
->HandleTableLock
);
260 ConSrvFreeHandlesTable(PCONSOLE_PROCESS_DATA ProcessData
)
262 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
264 if (ProcessData
->HandleTable
!= NULL
)
269 * ProcessData->ConsoleHandle is NULL (and the assertion fails) when
270 * ConSrvFreeHandlesTable is called in ConSrvConnect during the
271 * allocation of a new console.
273 // ASSERT(ProcessData->ConsoleHandle);
274 if (ProcessData
->ConsoleHandle
!= NULL
)
276 /* Close all the console handles */
277 for (i
= 0; i
< ProcessData
->HandleTableSize
; i
++)
279 ConSrvCloseHandleEntry(&ProcessData
->HandleTable
[i
]);
282 /* Free the handles table memory */
283 ConsoleFreeHeap(ProcessData
->HandleTable
);
284 ProcessData
->HandleTable
= NULL
;
287 ProcessData
->HandleTableSize
= 0;
289 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
294 ConSrvInitObject(IN OUT PCONSOLE_IO_OBJECT Object
,
295 IN CONSOLE_IO_OBJECT_TYPE Type
,
299 // if (!Object) return;
302 Object
->Console
= Console
;
303 Object
->AccessRead
= Object
->AccessWrite
= 0;
304 Object
->ExclusiveRead
= Object
->ExclusiveWrite
= 0;
305 Object
->HandleCount
= 0;
310 ConSrvInsertObject(PCONSOLE_PROCESS_DATA ProcessData
,
312 PCONSOLE_IO_OBJECT Object
,
317 #define IO_HANDLES_INCREMENT 2 * 3
320 PCONSOLE_IO_HANDLE Block
;
322 // NOTE: Commented out because calling code always lock HandleTableLock before.
323 // RtlEnterCriticalSection(&ProcessData->HandleTableLock);
325 ASSERT( (ProcessData
->HandleTable
== NULL
&& ProcessData
->HandleTableSize
== 0) ||
326 (ProcessData
->HandleTable
!= NULL
&& ProcessData
->HandleTableSize
!= 0) );
328 if (ProcessData
->HandleTable
)
330 for (i
= 0; i
< ProcessData
->HandleTableSize
; i
++)
332 if (ProcessData
->HandleTable
[i
].Object
== NULL
)
337 if (i
>= ProcessData
->HandleTableSize
)
339 /* Allocate a new handles table */
340 Block
= ConsoleAllocHeap(HEAP_ZERO_MEMORY
,
341 (ProcessData
->HandleTableSize
+
342 IO_HANDLES_INCREMENT
) * sizeof(CONSOLE_IO_HANDLE
));
345 // RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
346 return STATUS_UNSUCCESSFUL
;
349 /* If we previously had a handles table, free it and use the new one */
350 if (ProcessData
->HandleTable
)
352 /* Copy the handles from the old table to the new one */
354 ProcessData
->HandleTable
,
355 ProcessData
->HandleTableSize
* sizeof(CONSOLE_IO_HANDLE
));
356 ConsoleFreeHeap(ProcessData
->HandleTable
);
358 ProcessData
->HandleTable
= Block
;
359 ProcessData
->HandleTableSize
+= IO_HANDLES_INCREMENT
;
362 ProcessData
->HandleTable
[i
].Object
= Object
;
363 ProcessData
->HandleTable
[i
].Access
= Access
;
364 ProcessData
->HandleTable
[i
].Inheritable
= Inheritable
;
365 ProcessData
->HandleTable
[i
].ShareMode
= ShareMode
;
366 ConSrvCreateHandleEntry(&ProcessData
->HandleTable
[i
]);
367 *Handle
= ULongToHandle((i
<< 2) | 0x3);
369 // RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
371 return STATUS_SUCCESS
;
376 ConSrvRemoveObject(PCONSOLE_PROCESS_DATA ProcessData
,
379 ULONG Index
= HandleToULong(Handle
) >> 2;
381 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
383 ASSERT(ProcessData
->HandleTable
);
384 // ASSERT( (ProcessData->HandleTable == NULL && ProcessData->HandleTableSize == 0) ||
385 // (ProcessData->HandleTable != NULL && ProcessData->HandleTableSize != 0) );
387 if (Index
>= ProcessData
->HandleTableSize
||
388 ProcessData
->HandleTable
[Index
].Object
== NULL
)
390 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
391 return STATUS_INVALID_HANDLE
;
394 ASSERT(ProcessData
->ConsoleHandle
);
395 ConSrvCloseHandleEntry(&ProcessData
->HandleTable
[Index
]);
397 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
398 return STATUS_SUCCESS
;
403 ConSrvGetObject(PCONSOLE_PROCESS_DATA ProcessData
,
405 PCONSOLE_IO_OBJECT
* Object
,
406 PVOID
* Entry OPTIONAL
,
409 CONSOLE_IO_OBJECT_TYPE Type
)
412 ULONG Index
= HandleToULong(Handle
) >> 2;
413 PCONSOLE_IO_HANDLE HandleEntry
= NULL
;
414 PCONSOLE_IO_OBJECT ObjectEntry
= NULL
;
415 // PCONSOLE ObjectConsole;
418 if (Entry
) *Entry
= NULL
;
420 DPRINT("ConSrvGetObject -- Object: 0x%x, Handle: 0x%x\n", Object
, Handle
);
422 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
424 if ( IsConsoleHandle(Handle
) &&
425 Index
< ProcessData
->HandleTableSize
)
427 HandleEntry
= &ProcessData
->HandleTable
[Index
];
428 ObjectEntry
= HandleEntry
->Object
;
431 if ( HandleEntry
== NULL
||
432 ObjectEntry
== NULL
||
433 (HandleEntry
->Access
& Access
) == 0 ||
434 /*(Type != 0 && ObjectEntry->Type != Type)*/
435 (Type
!= 0 && (ObjectEntry
->Type
& Type
) == 0) )
437 DPRINT("ConSrvGetObject -- Invalid handle 0x%x of type %lu with access %lu ; retrieved object 0x%x (handle 0x%x) of type %lu with access %lu\n",
438 Handle
, Type
, Access
, ObjectEntry
, HandleEntry
, (ObjectEntry
? ObjectEntry
->Type
: 0), (HandleEntry
? HandleEntry
->Access
: 0));
440 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
441 return STATUS_INVALID_HANDLE
;
444 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
446 // Status = ConDrvGetConsole(&ObjectConsole, ProcessData->ConsoleHandle, LockConsole);
447 // if (NT_SUCCESS(Status))
448 if (ConDrvValidateConsoleUnsafe(ObjectEntry
->Console
, CONSOLE_RUNNING
, LockConsole
))
450 _InterlockedIncrement(&ObjectEntry
->Console
->ReferenceCount
);
452 /* Return the objects to the caller */
453 *Object
= ObjectEntry
;
454 if (Entry
) *Entry
= HandleEntry
;
456 // RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
457 return STATUS_SUCCESS
;
461 // RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
462 return STATUS_INVALID_HANDLE
;
468 ConSrvReleaseObject(PCONSOLE_IO_OBJECT Object
,
469 BOOL IsConsoleLocked
)
471 ConSrvReleaseConsole(Object
->Console
, IsConsoleLocked
);
476 ConSrvAllocateConsole(PCONSOLE_PROCESS_DATA ProcessData
,
477 PHANDLE pInputHandle
,
478 PHANDLE pOutputHandle
,
479 PHANDLE pErrorHandle
,
480 PCONSOLE_START_INFO ConsoleStartInfo
)
482 NTSTATUS Status
= STATUS_SUCCESS
;
483 HANDLE ConsoleHandle
;
487 * We are about to create a new console. However when ConSrvNewProcess
488 * was called, we didn't know that we wanted to create a new console and
489 * therefore, we by default inherited the handles table from our parent
490 * process. It's only now that we notice that in fact we do not need
491 * them, because we've created a new console and thus we must use it.
493 * Therefore, free the handles table so that we can recreate
494 * a new one later on.
496 ConSrvFreeHandlesTable(ProcessData
);
498 /* Initialize a new Console owned by this process */
499 Status
= ConSrvInitConsole(&ConsoleHandle
,
502 HandleToUlong(ProcessData
->Process
->ClientId
.UniqueProcess
));
503 if (!NT_SUCCESS(Status
))
505 DPRINT1("Console initialization failed\n");
509 /* Assign the new console handle */
510 ProcessData
->ConsoleHandle
= ConsoleHandle
;
512 /* Initialize the handles table */
513 Status
= ConSrvInitHandlesTable(ProcessData
,
518 if (!NT_SUCCESS(Status
))
520 DPRINT1("Failed to initialize the handles table\n");
521 ConSrvDeleteConsole(Console
);
522 ProcessData
->ConsoleHandle
= NULL
;
526 /* Duplicate the Input Event */
527 Status
= NtDuplicateObject(NtCurrentProcess(),
528 Console
->InputBuffer
.ActiveEvent
,
529 ProcessData
->Process
->ProcessHandle
,
530 &ProcessData
->ConsoleEvent
,
531 EVENT_ALL_ACCESS
, 0, 0);
532 if (!NT_SUCCESS(Status
))
534 DPRINT1("NtDuplicateObject() failed: %lu\n", Status
);
535 ConSrvFreeHandlesTable(ProcessData
);
536 ConSrvDeleteConsole(Console
);
537 ProcessData
->ConsoleHandle
= NULL
;
541 /* Insert the process into the processes list of the console */
542 InsertHeadList(&Console
->ProcessList
, &ProcessData
->ConsoleLink
);
544 /* Add a reference count because the process is tied to the console */
545 _InterlockedIncrement(&Console
->ReferenceCount
);
547 /* Update the internal info of the terminal */
548 TermRefreshInternalInfo(Console
);
550 return STATUS_SUCCESS
;
555 ConSrvInheritConsole(PCONSOLE_PROCESS_DATA ProcessData
,
556 HANDLE ConsoleHandle
,
557 BOOL CreateNewHandlesTable
,
558 PHANDLE pInputHandle
,
559 PHANDLE pOutputHandle
,
560 PHANDLE pErrorHandle
)
562 NTSTATUS Status
= STATUS_SUCCESS
;
565 /* Validate and lock the console */
566 if (!ConDrvValidateConsole(&Console
,
568 CONSOLE_RUNNING
, TRUE
))
570 // FIXME: Find another status code
571 return STATUS_UNSUCCESSFUL
;
574 /* Inherit the console */
575 ProcessData
->ConsoleHandle
= ConsoleHandle
;
577 if (CreateNewHandlesTable
)
580 * We are about to create a new console. However when ConSrvNewProcess
581 * was called, we didn't know that we wanted to create a new console and
582 * therefore, we by default inherited the handles table from our parent
583 * process. It's only now that we notice that in fact we do not need
584 * them, because we've created a new console and thus we must use it.
586 * Therefore, free the handles table so that we can recreate
587 * a new one later on.
589 ConSrvFreeHandlesTable(ProcessData
);
591 /* Initialize the handles table */
592 Status
= ConSrvInitHandlesTable(ProcessData
,
597 if (!NT_SUCCESS(Status
))
599 DPRINT1("Failed to initialize the handles table\n");
600 ProcessData
->ConsoleHandle
= NULL
;
605 /* Duplicate the Input Event */
606 Status
= NtDuplicateObject(NtCurrentProcess(),
607 Console
->InputBuffer
.ActiveEvent
,
608 ProcessData
->Process
->ProcessHandle
,
609 &ProcessData
->ConsoleEvent
,
610 EVENT_ALL_ACCESS
, 0, 0);
611 if (!NT_SUCCESS(Status
))
613 DPRINT1("NtDuplicateObject() failed: %lu\n", Status
);
614 ConSrvFreeHandlesTable(ProcessData
); // NOTE: Always free the handles table.
615 ProcessData
->ConsoleHandle
= NULL
;
619 /* Insert the process into the processes list of the console */
620 InsertHeadList(&Console
->ProcessList
, &ProcessData
->ConsoleLink
);
622 /* Add a reference count because the process is tied to the console */
623 _InterlockedIncrement(&Console
->ReferenceCount
);
625 /* Update the internal info of the terminal */
626 TermRefreshInternalInfo(Console
);
628 Status
= STATUS_SUCCESS
;
631 /* Unlock the console and return */
632 LeaveCriticalSection(&Console
->Lock
);
638 ConSrvRemoveConsole(PCONSOLE_PROCESS_DATA ProcessData
)
642 DPRINT("ConSrvRemoveConsole\n");
644 // RtlEnterCriticalSection(&ProcessData->HandleTableLock);
646 /* Validate and lock the console */
647 if (ConDrvValidateConsole(&Console
,
648 ProcessData
->ConsoleHandle
,
649 CONSOLE_RUNNING
, TRUE
))
651 DPRINT("ConSrvRemoveConsole - Locking OK\n");
653 /* Close all console handles and free the handles table */
654 ConSrvFreeHandlesTable(ProcessData
);
656 /* Detach the process from the console */
657 ProcessData
->ConsoleHandle
= NULL
;
659 /* Remove ourselves from the console's list of processes */
660 RemoveEntryList(&ProcessData
->ConsoleLink
);
662 /* Update the internal info of the terminal */
663 TermRefreshInternalInfo(Console
);
665 /* Release the console */
666 DPRINT("ConSrvRemoveConsole - Decrement Console->ReferenceCount = %lu\n", Console
->ReferenceCount
);
667 ConDrvReleaseConsole(Console
, TRUE
);
668 //CloseHandle(ProcessData->ConsoleEvent);
669 //ProcessData->ConsoleEvent = NULL;
672 // RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
676 /* PUBLIC SERVER APIS *********************************************************/
678 CSR_API(SrvOpenConsole
)
681 * This API opens a handle to either the input buffer or to
682 * a screen-buffer of the console of the current process.
686 PCONSOLE_OPENCONSOLE OpenConsoleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.OpenConsoleRequest
;
687 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
690 DWORD DesiredAccess
= OpenConsoleRequest
->DesiredAccess
;
691 DWORD ShareMode
= OpenConsoleRequest
->ShareMode
;
692 PCONSOLE_IO_OBJECT Object
;
694 OpenConsoleRequest
->Handle
= INVALID_HANDLE_VALUE
;
696 Status
= ConSrvGetConsole(ProcessData
, &Console
, TRUE
);
697 if (!NT_SUCCESS(Status
))
699 DPRINT1("Can't get console\n");
703 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
706 * Open a handle to either the active screen buffer or the input buffer.
708 if (OpenConsoleRequest
->HandleType
== HANDLE_OUTPUT
)
710 Object
= &Console
->ActiveBuffer
->Header
;
714 Object
= &Console
->InputBuffer
.Header
;
717 if (((DesiredAccess
& GENERIC_READ
) && Object
->ExclusiveRead
!= 0) ||
718 ((DesiredAccess
& GENERIC_WRITE
) && Object
->ExclusiveWrite
!= 0) ||
719 (!(ShareMode
& FILE_SHARE_READ
) && Object
->AccessRead
!= 0) ||
720 (!(ShareMode
& FILE_SHARE_WRITE
) && Object
->AccessWrite
!= 0))
722 DPRINT1("Sharing violation\n");
723 Status
= STATUS_SHARING_VIOLATION
;
727 Status
= ConSrvInsertObject(ProcessData
,
728 &OpenConsoleRequest
->Handle
,
731 OpenConsoleRequest
->InheritHandle
,
735 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
737 ConSrvReleaseConsole(Console
, TRUE
);
741 CSR_API(SrvDuplicateHandle
)
744 PCONSOLE_DUPLICATEHANDLE DuplicateHandleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.DuplicateHandleRequest
;
745 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
748 HANDLE SourceHandle
= DuplicateHandleRequest
->SourceHandle
;
749 ULONG Index
= HandleToULong(SourceHandle
) >> 2;
750 PCONSOLE_IO_HANDLE Entry
;
753 DuplicateHandleRequest
->TargetHandle
= INVALID_HANDLE_VALUE
;
755 Status
= ConSrvGetConsole(ProcessData
, &Console
, TRUE
);
756 if (!NT_SUCCESS(Status
))
758 DPRINT1("Can't get console\n");
762 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
764 // ASSERT( (ProcessData->HandleTable == NULL && ProcessData->HandleTableSize == 0) ||
765 // (ProcessData->HandleTable != NULL && ProcessData->HandleTableSize != 0) );
767 if ( /** !IsConsoleHandle(SourceHandle) || **/
768 Index
>= ProcessData
->HandleTableSize
||
769 (Entry
= &ProcessData
->HandleTable
[Index
])->Object
== NULL
)
771 DPRINT1("Couldn't duplicate invalid handle 0x%p\n", SourceHandle
);
772 Status
= STATUS_INVALID_HANDLE
;
776 if (DuplicateHandleRequest
->Options
& DUPLICATE_SAME_ACCESS
)
778 DesiredAccess
= Entry
->Access
;
782 DesiredAccess
= DuplicateHandleRequest
->DesiredAccess
;
783 /* Make sure the source handle has all the desired flags */
784 if ((Entry
->Access
& DesiredAccess
) == 0)
786 DPRINT1("Handle 0x%p only has access %X; requested %X\n",
787 SourceHandle
, Entry
->Access
, DesiredAccess
);
788 Status
= STATUS_INVALID_PARAMETER
;
793 /* Insert the new handle inside the process handles table */
794 Status
= ConSrvInsertObject(ProcessData
,
795 &DuplicateHandleRequest
->TargetHandle
,
798 DuplicateHandleRequest
->InheritHandle
,
800 if (NT_SUCCESS(Status
) &&
801 (DuplicateHandleRequest
->Options
& DUPLICATE_CLOSE_SOURCE
))
803 /* Close the original handle if needed */
804 ConSrvCloseHandleEntry(Entry
);
808 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
810 ConSrvReleaseConsole(Console
, TRUE
);
814 CSR_API(SrvGetHandleInformation
)
817 PCONSOLE_GETHANDLEINFO GetHandleInfoRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetHandleInfoRequest
;
818 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
821 HANDLE Handle
= GetHandleInfoRequest
->Handle
;
822 ULONG Index
= HandleToULong(Handle
) >> 2;
823 PCONSOLE_IO_HANDLE Entry
;
825 Status
= ConSrvGetConsole(ProcessData
, &Console
, TRUE
);
826 if (!NT_SUCCESS(Status
))
828 DPRINT1("Can't get console\n");
832 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
834 ASSERT(ProcessData
->HandleTable
);
835 // ASSERT( (ProcessData->HandleTable == NULL && ProcessData->HandleTableSize == 0) ||
836 // (ProcessData->HandleTable != NULL && ProcessData->HandleTableSize != 0) );
838 if (!IsConsoleHandle(Handle
) ||
839 Index
>= ProcessData
->HandleTableSize
||
840 (Entry
= &ProcessData
->HandleTable
[Index
])->Object
== NULL
)
842 Status
= STATUS_INVALID_HANDLE
;
847 * Retrieve the handle information flags. The console server
848 * doesn't support HANDLE_FLAG_PROTECT_FROM_CLOSE.
850 GetHandleInfoRequest
->Flags
= 0;
851 if (Entry
->Inheritable
) GetHandleInfoRequest
->Flags
|= HANDLE_FLAG_INHERIT
;
853 Status
= STATUS_SUCCESS
;
856 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
858 ConSrvReleaseConsole(Console
, TRUE
);
862 CSR_API(SrvSetHandleInformation
)
865 PCONSOLE_SETHANDLEINFO SetHandleInfoRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.SetHandleInfoRequest
;
866 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
869 HANDLE Handle
= SetHandleInfoRequest
->Handle
;
870 ULONG Index
= HandleToULong(Handle
) >> 2;
871 PCONSOLE_IO_HANDLE Entry
;
873 Status
= ConSrvGetConsole(ProcessData
, &Console
, TRUE
);
874 if (!NT_SUCCESS(Status
))
876 DPRINT1("Can't get console\n");
880 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
882 ASSERT(ProcessData
->HandleTable
);
883 // ASSERT( (ProcessData->HandleTable == NULL && ProcessData->HandleTableSize == 0) ||
884 // (ProcessData->HandleTable != NULL && ProcessData->HandleTableSize != 0) );
886 if (!IsConsoleHandle(Handle
) ||
887 Index
>= ProcessData
->HandleTableSize
||
888 (Entry
= &ProcessData
->HandleTable
[Index
])->Object
== NULL
)
890 Status
= STATUS_INVALID_HANDLE
;
895 * Modify the handle information flags. The console server
896 * doesn't support HANDLE_FLAG_PROTECT_FROM_CLOSE.
898 if (SetHandleInfoRequest
->Mask
& HANDLE_FLAG_INHERIT
)
900 Entry
->Inheritable
= ((SetHandleInfoRequest
->Flags
& HANDLE_FLAG_INHERIT
) != 0);
903 Status
= STATUS_SUCCESS
;
906 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
908 ConSrvReleaseConsole(Console
, TRUE
);
912 CSR_API(SrvCloseHandle
)
915 PCONSOLE_CLOSEHANDLE CloseHandleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.CloseHandleRequest
;
916 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
919 Status
= ConSrvGetConsole(ProcessData
, &Console
, TRUE
);
920 if (!NT_SUCCESS(Status
))
922 DPRINT1("Can't get console\n");
926 Status
= ConSrvRemoveObject(ProcessData
, CloseHandleRequest
->Handle
);
928 ConSrvReleaseConsole(Console
, TRUE
);
932 CSR_API(SrvVerifyConsoleIoHandle
)
935 PCONSOLE_VERIFYHANDLE VerifyHandleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.VerifyHandleRequest
;
936 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
939 HANDLE IoHandle
= VerifyHandleRequest
->Handle
;
940 ULONG Index
= HandleToULong(IoHandle
) >> 2;
942 VerifyHandleRequest
->IsValid
= FALSE
;
944 Status
= ConSrvGetConsole(ProcessData
, &Console
, TRUE
);
945 if (!NT_SUCCESS(Status
))
947 DPRINT1("Can't get console\n");
951 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
953 // ASSERT( (ProcessData->HandleTable == NULL && ProcessData->HandleTableSize == 0) ||
954 // (ProcessData->HandleTable != NULL && ProcessData->HandleTableSize != 0) );
956 if (!IsConsoleHandle(IoHandle
) ||
957 Index
>= ProcessData
->HandleTableSize
||
958 ProcessData
->HandleTable
[Index
].Object
== NULL
)
960 DPRINT("SrvVerifyConsoleIoHandle failed\n");
964 VerifyHandleRequest
->IsValid
= TRUE
;
967 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
969 ConSrvReleaseConsole(Console
, TRUE
);
970 return STATUS_SUCCESS
;