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;
380 PCONSOLE_IO_OBJECT Object
;
382 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
384 ASSERT(ProcessData
->HandleTable
);
385 // ASSERT( (ProcessData->HandleTable == NULL && ProcessData->HandleTableSize == 0) ||
386 // (ProcessData->HandleTable != NULL && ProcessData->HandleTableSize != 0) );
388 if (Index
>= ProcessData
->HandleTableSize
||
389 (Object
= ProcessData
->HandleTable
[Index
].Object
) == NULL
)
391 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
392 return STATUS_INVALID_HANDLE
;
395 ASSERT(ProcessData
->ConsoleHandle
);
396 ConSrvCloseHandleEntry(&ProcessData
->HandleTable
[Index
]);
398 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
399 return STATUS_SUCCESS
;
404 ConSrvGetObject(PCONSOLE_PROCESS_DATA ProcessData
,
406 PCONSOLE_IO_OBJECT
* Object
,
407 PVOID
* Entry OPTIONAL
,
410 CONSOLE_IO_OBJECT_TYPE Type
)
413 ULONG Index
= HandleToULong(Handle
) >> 2;
414 PCONSOLE_IO_HANDLE HandleEntry
= NULL
;
415 PCONSOLE_IO_OBJECT ObjectEntry
= NULL
;
416 // PCONSOLE ObjectConsole;
419 if (Entry
) *Entry
= NULL
;
421 DPRINT("ConSrvGetObject -- Object: 0x%x, Handle: 0x%x\n", Object
, Handle
);
423 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
425 if ( IsConsoleHandle(Handle
) &&
426 Index
< ProcessData
->HandleTableSize
)
428 HandleEntry
= &ProcessData
->HandleTable
[Index
];
429 ObjectEntry
= HandleEntry
->Object
;
432 if ( HandleEntry
== NULL
||
433 ObjectEntry
== NULL
||
434 (HandleEntry
->Access
& Access
) == 0 ||
435 /*(Type != 0 && ObjectEntry->Type != Type)*/
436 (Type
!= 0 && (ObjectEntry
->Type
& Type
) == 0) )
438 DPRINT1("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",
439 Handle
, Type
, Access
, ObjectEntry
, HandleEntry
, (ObjectEntry
? ObjectEntry
->Type
: 0), (HandleEntry
? HandleEntry
->Access
: 0));
441 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
442 return STATUS_INVALID_HANDLE
;
445 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
447 // Status = ConDrvGetConsole(&ObjectConsole, ProcessData->ConsoleHandle, LockConsole);
448 // if (NT_SUCCESS(Status))
449 if (ConDrvValidateConsoleUnsafe(ObjectEntry
->Console
, CONSOLE_RUNNING
, LockConsole
))
451 _InterlockedIncrement(&ObjectEntry
->Console
->ReferenceCount
);
453 /* Return the objects to the caller */
454 *Object
= ObjectEntry
;
455 if (Entry
) *Entry
= HandleEntry
;
457 // RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
458 return STATUS_SUCCESS
;
462 // RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
463 return STATUS_INVALID_HANDLE
;
469 ConSrvReleaseObject(PCONSOLE_IO_OBJECT Object
,
470 BOOL IsConsoleLocked
)
472 ConSrvReleaseConsole(Object
->Console
, IsConsoleLocked
);
477 ConSrvAllocateConsole(PCONSOLE_PROCESS_DATA ProcessData
,
478 PHANDLE pInputHandle
,
479 PHANDLE pOutputHandle
,
480 PHANDLE pErrorHandle
,
481 PCONSOLE_START_INFO ConsoleStartInfo
)
483 NTSTATUS Status
= STATUS_SUCCESS
;
484 HANDLE ConsoleHandle
;
488 * We are about to create a new console. However when ConSrvNewProcess
489 * was called, we didn't know that we wanted to create a new console and
490 * therefore, we by default inherited the handles table from our parent
491 * process. It's only now that we notice that in fact we do not need
492 * them, because we've created a new console and thus we must use it.
494 * Therefore, free the handles table so that we can recreate
495 * a new one later on.
497 ConSrvFreeHandlesTable(ProcessData
);
499 /* Initialize a new Console owned by this process */
500 Status
= ConSrvInitConsole(&ConsoleHandle
,
503 HandleToUlong(ProcessData
->Process
->ClientId
.UniqueProcess
));
504 if (!NT_SUCCESS(Status
))
506 DPRINT1("Console initialization failed\n");
510 /* Assign the new console handle */
511 ProcessData
->ConsoleHandle
= ConsoleHandle
;
513 /* Initialize the handles table */
514 Status
= ConSrvInitHandlesTable(ProcessData
,
519 if (!NT_SUCCESS(Status
))
521 DPRINT1("Failed to initialize the handles table\n");
522 ConSrvDeleteConsole(Console
);
523 ProcessData
->ConsoleHandle
= NULL
;
527 /* Duplicate the Input Event */
528 Status
= NtDuplicateObject(NtCurrentProcess(),
529 Console
->InputBuffer
.ActiveEvent
,
530 ProcessData
->Process
->ProcessHandle
,
531 &ProcessData
->ConsoleEvent
,
532 EVENT_ALL_ACCESS
, 0, 0);
533 if (!NT_SUCCESS(Status
))
535 DPRINT1("NtDuplicateObject() failed: %lu\n", Status
);
536 ConSrvFreeHandlesTable(ProcessData
);
537 ConSrvDeleteConsole(Console
);
538 ProcessData
->ConsoleHandle
= NULL
;
542 /* Insert the process into the processes list of the console */
543 InsertHeadList(&Console
->ProcessList
, &ProcessData
->ConsoleLink
);
545 /* Add a reference count because the process is tied to the console */
546 _InterlockedIncrement(&Console
->ReferenceCount
);
548 /* Update the internal info of the terminal */
549 TermRefreshInternalInfo(Console
);
551 return STATUS_SUCCESS
;
556 ConSrvInheritConsole(PCONSOLE_PROCESS_DATA ProcessData
,
557 HANDLE ConsoleHandle
,
558 BOOL CreateNewHandlesTable
,
559 PHANDLE pInputHandle
,
560 PHANDLE pOutputHandle
,
561 PHANDLE pErrorHandle
)
563 NTSTATUS Status
= STATUS_SUCCESS
;
566 /* Validate and lock the console */
567 if (!ConDrvValidateConsole(&Console
,
569 CONSOLE_RUNNING
, TRUE
))
571 // FIXME: Find another status code
572 return STATUS_UNSUCCESSFUL
;
575 /* Inherit the console */
576 ProcessData
->ConsoleHandle
= ConsoleHandle
;
578 if (CreateNewHandlesTable
)
581 * We are about to create a new console. However when ConSrvNewProcess
582 * was called, we didn't know that we wanted to create a new console and
583 * therefore, we by default inherited the handles table from our parent
584 * process. It's only now that we notice that in fact we do not need
585 * them, because we've created a new console and thus we must use it.
587 * Therefore, free the handles table so that we can recreate
588 * a new one later on.
590 ConSrvFreeHandlesTable(ProcessData
);
592 /* Initialize the handles table */
593 Status
= ConSrvInitHandlesTable(ProcessData
,
598 if (!NT_SUCCESS(Status
))
600 DPRINT1("Failed to initialize the handles table\n");
601 ProcessData
->ConsoleHandle
= NULL
;
606 /* Duplicate the Input Event */
607 Status
= NtDuplicateObject(NtCurrentProcess(),
608 Console
->InputBuffer
.ActiveEvent
,
609 ProcessData
->Process
->ProcessHandle
,
610 &ProcessData
->ConsoleEvent
,
611 EVENT_ALL_ACCESS
, 0, 0);
612 if (!NT_SUCCESS(Status
))
614 DPRINT1("NtDuplicateObject() failed: %lu\n", Status
);
615 ConSrvFreeHandlesTable(ProcessData
); // NOTE: Always free the handles table.
616 ProcessData
->ConsoleHandle
= NULL
;
620 /* Insert the process into the processes list of the console */
621 InsertHeadList(&Console
->ProcessList
, &ProcessData
->ConsoleLink
);
623 /* Add a reference count because the process is tied to the console */
624 _InterlockedIncrement(&Console
->ReferenceCount
);
626 /* Update the internal info of the terminal */
627 TermRefreshInternalInfo(Console
);
629 Status
= STATUS_SUCCESS
;
632 /* Unlock the console and return */
633 LeaveCriticalSection(&Console
->Lock
);
639 ConSrvRemoveConsole(PCONSOLE_PROCESS_DATA ProcessData
)
643 DPRINT("ConSrvRemoveConsole\n");
645 // RtlEnterCriticalSection(&ProcessData->HandleTableLock);
647 /* Validate and lock the console */
648 if (ConDrvValidateConsole(&Console
,
649 ProcessData
->ConsoleHandle
,
650 CONSOLE_RUNNING
, TRUE
))
652 DPRINT("ConSrvRemoveConsole - Locking OK\n");
654 /* Close all console handles and free the handles table */
655 ConSrvFreeHandlesTable(ProcessData
);
657 /* Detach the process from the console */
658 ProcessData
->ConsoleHandle
= NULL
;
660 /* Remove ourselves from the console's list of processes */
661 RemoveEntryList(&ProcessData
->ConsoleLink
);
663 /* Update the internal info of the terminal */
664 TermRefreshInternalInfo(Console
);
666 /* Release the console */
667 DPRINT("ConSrvRemoveConsole - Decrement Console->ReferenceCount = %lu\n", Console
->ReferenceCount
);
668 ConDrvReleaseConsole(Console
, TRUE
);
669 //CloseHandle(ProcessData->ConsoleEvent);
670 //ProcessData->ConsoleEvent = NULL;
673 // RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
677 /* PUBLIC SERVER APIS *********************************************************/
679 CSR_API(SrvOpenConsole
)
682 * This API opens a handle to either the input buffer or to
683 * a screen-buffer of the console of the current process.
687 PCONSOLE_OPENCONSOLE OpenConsoleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.OpenConsoleRequest
;
688 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
691 DWORD DesiredAccess
= OpenConsoleRequest
->Access
;
692 DWORD ShareMode
= OpenConsoleRequest
->ShareMode
;
693 PCONSOLE_IO_OBJECT Object
;
695 OpenConsoleRequest
->ConsoleHandle
= INVALID_HANDLE_VALUE
;
697 Status
= ConSrvGetConsole(ProcessData
, &Console
, TRUE
);
698 if (!NT_SUCCESS(Status
))
700 DPRINT1("Can't get console\n");
704 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
707 * Open a handle to either the active screen buffer or the input buffer.
709 if (OpenConsoleRequest
->HandleType
== HANDLE_OUTPUT
)
711 Object
= &Console
->ActiveBuffer
->Header
;
715 Object
= &Console
->InputBuffer
.Header
;
718 if (((DesiredAccess
& GENERIC_READ
) && Object
->ExclusiveRead
!= 0) ||
719 ((DesiredAccess
& GENERIC_WRITE
) && Object
->ExclusiveWrite
!= 0) ||
720 (!(ShareMode
& FILE_SHARE_READ
) && Object
->AccessRead
!= 0) ||
721 (!(ShareMode
& FILE_SHARE_WRITE
) && Object
->AccessWrite
!= 0))
723 DPRINT1("Sharing violation\n");
724 Status
= STATUS_SHARING_VIOLATION
;
728 Status
= ConSrvInsertObject(ProcessData
,
729 &OpenConsoleRequest
->ConsoleHandle
,
732 OpenConsoleRequest
->Inheritable
,
736 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
738 ConSrvReleaseConsole(Console
, TRUE
);
742 CSR_API(SrvDuplicateHandle
)
745 PCONSOLE_DUPLICATEHANDLE DuplicateHandleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.DuplicateHandleRequest
;
746 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
749 HANDLE ConsoleHandle
= DuplicateHandleRequest
->ConsoleHandle
;
750 ULONG Index
= HandleToULong(ConsoleHandle
) >> 2;
751 PCONSOLE_IO_HANDLE Entry
;
754 Status
= ConSrvGetConsole(ProcessData
, &Console
, TRUE
);
755 if (!NT_SUCCESS(Status
))
757 DPRINT1("Can't get console\n");
761 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
763 // ASSERT( (ProcessData->HandleTable == NULL && ProcessData->HandleTableSize == 0) ||
764 // (ProcessData->HandleTable != NULL && ProcessData->HandleTableSize != 0) );
766 if ( /** !IsConsoleHandle(ConsoleHandle) || **/
767 Index
>= ProcessData
->HandleTableSize
||
768 (Entry
= &ProcessData
->HandleTable
[Index
])->Object
== NULL
)
770 DPRINT1("Couldn't duplicate invalid handle %p\n", ConsoleHandle
);
771 Status
= STATUS_INVALID_HANDLE
;
775 if (DuplicateHandleRequest
->Options
& DUPLICATE_SAME_ACCESS
)
777 DesiredAccess
= Entry
->Access
;
781 DesiredAccess
= DuplicateHandleRequest
->Access
;
782 /* Make sure the source handle has all the desired flags */
783 if ((Entry
->Access
& DesiredAccess
) == 0)
785 DPRINT1("Handle %p only has access %X; requested %X\n",
786 ConsoleHandle
, Entry
->Access
, DesiredAccess
);
787 Status
= STATUS_INVALID_PARAMETER
;
792 /* Insert the new handle inside the process handles table */
793 Status
= ConSrvInsertObject(ProcessData
,
794 &DuplicateHandleRequest
->ConsoleHandle
, // Use the new handle value!
797 DuplicateHandleRequest
->Inheritable
,
799 if (NT_SUCCESS(Status
) &&
800 (DuplicateHandleRequest
->Options
& DUPLICATE_CLOSE_SOURCE
))
802 /* Close the original handle if needed */
803 ConSrvCloseHandleEntry(Entry
);
807 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
809 ConSrvReleaseConsole(Console
, TRUE
);
813 CSR_API(SrvGetHandleInformation
)
815 DPRINT1("%s not yet implemented\n", __FUNCTION__
);
816 return STATUS_NOT_IMPLEMENTED
;
819 CSR_API(SrvSetHandleInformation
)
821 DPRINT1("%s not yet implemented\n", __FUNCTION__
);
822 return STATUS_NOT_IMPLEMENTED
;
825 CSR_API(SrvCloseHandle
)
828 PCONSOLE_CLOSEHANDLE CloseHandleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.CloseHandleRequest
;
829 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
832 Status
= ConSrvGetConsole(ProcessData
, &Console
, TRUE
);
833 if (!NT_SUCCESS(Status
))
835 DPRINT1("Can't get console\n");
839 Status
= ConSrvRemoveObject(ProcessData
, CloseHandleRequest
->ConsoleHandle
);
841 ConSrvReleaseConsole(Console
, TRUE
);
845 CSR_API(SrvVerifyConsoleIoHandle
)
848 PCONSOLE_VERIFYHANDLE VerifyHandleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.VerifyHandleRequest
;
849 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
852 HANDLE ConsoleHandle
= VerifyHandleRequest
->ConsoleHandle
;
853 ULONG Index
= HandleToULong(ConsoleHandle
) >> 2;
855 Status
= ConSrvGetConsole(ProcessData
, &Console
, TRUE
);
856 if (!NT_SUCCESS(Status
))
858 DPRINT1("Can't get console\n");
862 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
864 // ASSERT( (ProcessData->HandleTable == NULL && ProcessData->HandleTableSize == 0) ||
865 // (ProcessData->HandleTable != NULL && ProcessData->HandleTableSize != 0) );
867 if (!IsConsoleHandle(ConsoleHandle
) ||
868 Index
>= ProcessData
->HandleTableSize
||
869 ProcessData
->HandleTable
[Index
].Object
== NULL
)
871 DPRINT("SrvVerifyConsoleIoHandle failed\n");
872 Status
= STATUS_INVALID_HANDLE
;
875 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
877 ConSrvReleaseConsole(Console
, TRUE
);