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 *******************************************************************/
14 #include "include/conio.h"
15 #include "include/conio2.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
,
139 OUT PHANDLE pInputHandle
,
140 OUT PHANDLE pOutputHandle
,
141 OUT PHANDLE pErrorHandle
)
144 HANDLE InputHandle
= INVALID_HANDLE_VALUE
,
145 OutputHandle
= INVALID_HANDLE_VALUE
,
146 ErrorHandle
= INVALID_HANDLE_VALUE
;
149 * Initialize the handles table. Use temporary variables to store
150 * the handles values in such a way that, if we fail, we don't
151 * return to the caller invalid handle values.
153 * Insert the IO handles.
156 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
158 /* Insert the Input handle */
159 Status
= ConSrvInsertObject(ProcessData
,
161 &Console
->InputBuffer
.Header
,
162 GENERIC_READ
| GENERIC_WRITE
,
164 FILE_SHARE_READ
| FILE_SHARE_WRITE
);
165 if (!NT_SUCCESS(Status
))
167 DPRINT1("Failed to insert the input handle\n");
168 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
169 ConSrvFreeHandlesTable(ProcessData
);
173 /* Insert the Output handle */
174 Status
= ConSrvInsertObject(ProcessData
,
176 &Console
->ActiveBuffer
->Header
,
177 GENERIC_READ
| GENERIC_WRITE
,
179 FILE_SHARE_READ
| FILE_SHARE_WRITE
);
180 if (!NT_SUCCESS(Status
))
182 DPRINT1("Failed to insert the output handle\n");
183 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
184 ConSrvFreeHandlesTable(ProcessData
);
188 /* Insert the Error handle */
189 Status
= ConSrvInsertObject(ProcessData
,
191 &Console
->ActiveBuffer
->Header
,
192 GENERIC_READ
| GENERIC_WRITE
,
194 FILE_SHARE_READ
| FILE_SHARE_WRITE
);
195 if (!NT_SUCCESS(Status
))
197 DPRINT1("Failed to insert the error handle\n");
198 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
199 ConSrvFreeHandlesTable(ProcessData
);
203 /* Return the newly created handles */
204 *pInputHandle
= InputHandle
;
205 *pOutputHandle
= OutputHandle
;
206 *pErrorHandle
= ErrorHandle
;
208 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
209 return STATUS_SUCCESS
;
213 ConSrvInheritHandlesTable(IN PCONSOLE_PROCESS_DATA SourceProcessData
,
214 IN PCONSOLE_PROCESS_DATA TargetProcessData
)
216 NTSTATUS Status
= STATUS_SUCCESS
;
219 RtlEnterCriticalSection(&SourceProcessData
->HandleTableLock
);
221 /* Inherit a handles table only if there is no already */
222 if (TargetProcessData
->HandleTable
!= NULL
/* || TargetProcessData->HandleTableSize != 0 */)
224 Status
= STATUS_UNSUCCESSFUL
;
228 /* Allocate a new handle table for the child process */
229 TargetProcessData
->HandleTable
= ConsoleAllocHeap(HEAP_ZERO_MEMORY
,
230 SourceProcessData
->HandleTableSize
231 * sizeof(CONSOLE_IO_HANDLE
));
232 if (TargetProcessData
->HandleTable
== NULL
)
234 Status
= STATUS_NO_MEMORY
;
238 TargetProcessData
->HandleTableSize
= SourceProcessData
->HandleTableSize
;
241 * Parse the parent process' handles table and, for each handle,
242 * do a copy of it and reference it, if the handle is inheritable.
244 for (i
= 0, j
= 0; i
< SourceProcessData
->HandleTableSize
; i
++)
246 if (SourceProcessData
->HandleTable
[i
].Object
!= NULL
&&
247 SourceProcessData
->HandleTable
[i
].Inheritable
)
250 * Copy the handle data and increment the reference count of the
251 * pointed object (via the call to ConSrvCreateHandleEntry).
253 TargetProcessData
->HandleTable
[j
] = SourceProcessData
->HandleTable
[i
];
254 ConSrvCreateHandleEntry(&TargetProcessData
->HandleTable
[j
]);
260 RtlLeaveCriticalSection(&SourceProcessData
->HandleTableLock
);
265 ConSrvFreeHandlesTable(PCONSOLE_PROCESS_DATA ProcessData
)
267 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
269 if (ProcessData
->HandleTable
!= NULL
)
274 * ProcessData->ConsoleHandle is NULL (and the assertion fails) when
275 * ConSrvFreeHandlesTable is called in ConSrvConnect during the
276 * allocation of a new console.
278 // ASSERT(ProcessData->ConsoleHandle);
279 if (ProcessData
->ConsoleHandle
!= NULL
)
281 /* Close all the console handles */
282 for (i
= 0; i
< ProcessData
->HandleTableSize
; i
++)
284 ConSrvCloseHandleEntry(&ProcessData
->HandleTable
[i
]);
287 /* Free the handles table memory */
288 ConsoleFreeHeap(ProcessData
->HandleTable
);
289 ProcessData
->HandleTable
= NULL
;
292 ProcessData
->HandleTableSize
= 0;
294 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
299 ConSrvInitObject(IN OUT PCONSOLE_IO_OBJECT Object
,
300 IN CONSOLE_IO_OBJECT_TYPE Type
,
304 // if (!Object) return;
307 Object
->Console
= Console
;
308 Object
->AccessRead
= Object
->AccessWrite
= 0;
309 Object
->ExclusiveRead
= Object
->ExclusiveWrite
= 0;
310 Object
->HandleCount
= 0;
315 ConSrvInsertObject(PCONSOLE_PROCESS_DATA ProcessData
,
317 PCONSOLE_IO_OBJECT Object
,
322 #define IO_HANDLES_INCREMENT 2 * 3
325 PCONSOLE_IO_HANDLE Block
;
327 // NOTE: Commented out because calling code always lock HandleTableLock before.
328 // RtlEnterCriticalSection(&ProcessData->HandleTableLock);
330 ASSERT( (ProcessData
->HandleTable
== NULL
&& ProcessData
->HandleTableSize
== 0) ||
331 (ProcessData
->HandleTable
!= NULL
&& ProcessData
->HandleTableSize
!= 0) );
333 if (ProcessData
->HandleTable
)
335 for (i
= 0; i
< ProcessData
->HandleTableSize
; i
++)
337 if (ProcessData
->HandleTable
[i
].Object
== NULL
)
342 if (i
>= ProcessData
->HandleTableSize
)
344 /* Allocate a new handles table */
345 Block
= ConsoleAllocHeap(HEAP_ZERO_MEMORY
,
346 (ProcessData
->HandleTableSize
+
347 IO_HANDLES_INCREMENT
) * sizeof(CONSOLE_IO_HANDLE
));
350 // RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
351 return STATUS_UNSUCCESSFUL
;
354 /* If we previously had a handles table, free it and use the new one */
355 if (ProcessData
->HandleTable
)
357 /* Copy the handles from the old table to the new one */
359 ProcessData
->HandleTable
,
360 ProcessData
->HandleTableSize
* sizeof(CONSOLE_IO_HANDLE
));
361 ConsoleFreeHeap(ProcessData
->HandleTable
);
363 ProcessData
->HandleTable
= Block
;
364 ProcessData
->HandleTableSize
+= IO_HANDLES_INCREMENT
;
367 ProcessData
->HandleTable
[i
].Object
= Object
;
368 ProcessData
->HandleTable
[i
].Access
= Access
;
369 ProcessData
->HandleTable
[i
].Inheritable
= Inheritable
;
370 ProcessData
->HandleTable
[i
].ShareMode
= ShareMode
;
371 ConSrvCreateHandleEntry(&ProcessData
->HandleTable
[i
]);
372 *Handle
= ULongToHandle((i
<< 2) | 0x3);
374 // RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
376 return STATUS_SUCCESS
;
381 ConSrvRemoveObject(PCONSOLE_PROCESS_DATA ProcessData
,
384 ULONG Index
= HandleToULong(Handle
) >> 2;
385 PCONSOLE_IO_OBJECT Object
;
387 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
389 ASSERT(ProcessData
->HandleTable
);
391 if (Index
>= ProcessData
->HandleTableSize
||
392 (Object
= ProcessData
->HandleTable
[Index
].Object
) == NULL
)
394 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
395 return STATUS_INVALID_HANDLE
;
398 ASSERT(ProcessData
->ConsoleHandle
);
399 ConSrvCloseHandleEntry(&ProcessData
->HandleTable
[Index
]);
401 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
402 return STATUS_SUCCESS
;
407 ConSrvGetObject(PCONSOLE_PROCESS_DATA ProcessData
,
409 PCONSOLE_IO_OBJECT
* Object
,
410 PVOID
* Entry OPTIONAL
,
413 CONSOLE_IO_OBJECT_TYPE Type
)
416 ULONG Index
= HandleToULong(Handle
) >> 2;
417 PCONSOLE_IO_HANDLE HandleEntry
= NULL
;
418 PCONSOLE_IO_OBJECT ObjectEntry
= NULL
;
419 // PCONSOLE ObjectConsole;
422 if (Entry
) *Entry
= NULL
;
424 DPRINT("ConSrvGetObject -- Object: 0x%x, Handle: 0x%x\n", Object
, Handle
);
426 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
428 if ( IsConsoleHandle(Handle
) &&
429 Index
< ProcessData
->HandleTableSize
)
431 HandleEntry
= &ProcessData
->HandleTable
[Index
];
432 ObjectEntry
= HandleEntry
->Object
;
435 if ( HandleEntry
== NULL
||
436 ObjectEntry
== NULL
||
437 (HandleEntry
->Access
& Access
) == 0 ||
438 /*(Type != 0 && ObjectEntry->Type != Type)*/
439 (Type
!= 0 && (ObjectEntry
->Type
& Type
) == 0) )
441 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",
442 Handle
, Type
, Access
, ObjectEntry
, HandleEntry
, (ObjectEntry
? ObjectEntry
->Type
: 0), (HandleEntry
? HandleEntry
->Access
: 0));
444 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
445 return STATUS_INVALID_HANDLE
;
448 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
450 // Status = ConDrvGetConsole(&ObjectConsole, ProcessData->ConsoleHandle, LockConsole);
451 // if (NT_SUCCESS(Status))
452 if (ConDrvValidateConsoleUnsafe(ObjectEntry
->Console
, CONSOLE_RUNNING
, LockConsole
))
454 _InterlockedIncrement(&ObjectEntry
->Console
->ReferenceCount
);
456 /* Return the objects to the caller */
457 *Object
= ObjectEntry
;
458 if (Entry
) *Entry
= HandleEntry
;
460 // RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
461 return STATUS_SUCCESS
;
465 // RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
466 return STATUS_INVALID_HANDLE
;
472 ConSrvReleaseObject(PCONSOLE_IO_OBJECT Object
,
473 BOOL IsConsoleLocked
)
475 ConSrvReleaseConsole(Object
->Console
, IsConsoleLocked
);
480 ConSrvAllocateConsole(PCONSOLE_PROCESS_DATA ProcessData
,
481 PHANDLE pInputHandle
,
482 PHANDLE pOutputHandle
,
483 PHANDLE pErrorHandle
,
484 PCONSOLE_START_INFO ConsoleStartInfo
)
486 NTSTATUS Status
= STATUS_SUCCESS
;
487 HANDLE ConsoleHandle
;
491 * We are about to create a new console. However when ConSrvNewProcess
492 * was called, we didn't know that we wanted to create a new console and
493 * therefore, we by default inherited the handles table from our parent
494 * process. It's only now that we notice that in fact we do not need
495 * them, because we've created a new console and thus we must use it.
497 * Therefore, free the handles table so that we can recreate
498 * a new one later on.
500 ConSrvFreeHandlesTable(ProcessData
);
502 /* Initialize a new Console owned by this process */
503 Status
= ConSrvInitConsole(&ConsoleHandle
,
506 HandleToUlong(ProcessData
->Process
->ClientId
.UniqueProcess
));
507 if (!NT_SUCCESS(Status
))
509 DPRINT1("Console initialization failed\n");
513 /* Assign the new console handle */
514 ProcessData
->ConsoleHandle
= ConsoleHandle
;
516 /* Initialize the handles table */
517 Status
= ConSrvInitHandlesTable(ProcessData
,
522 if (!NT_SUCCESS(Status
))
524 DPRINT1("Failed to initialize the handles table\n");
525 ConSrvDeleteConsole(Console
);
526 ProcessData
->ConsoleHandle
= NULL
;
530 /* Duplicate the Input Event */
531 Status
= NtDuplicateObject(NtCurrentProcess(),
532 Console
->InputBuffer
.ActiveEvent
,
533 ProcessData
->Process
->ProcessHandle
,
534 &ProcessData
->ConsoleEvent
,
535 EVENT_ALL_ACCESS
, 0, 0);
536 if (!NT_SUCCESS(Status
))
538 DPRINT1("NtDuplicateObject() failed: %lu\n", Status
);
539 ConSrvFreeHandlesTable(ProcessData
);
540 ConSrvDeleteConsole(Console
);
541 ProcessData
->ConsoleHandle
= NULL
;
545 /* Insert the process into the processes list of the console */
546 InsertHeadList(&Console
->ProcessList
, &ProcessData
->ConsoleLink
);
548 /* Add a reference count because the process is tied to the console */
549 _InterlockedIncrement(&Console
->ReferenceCount
);
551 /* Update the internal info of the terminal */
552 ConioRefreshInternalInfo(Console
);
554 return STATUS_SUCCESS
;
559 ConSrvInheritConsole(PCONSOLE_PROCESS_DATA ProcessData
,
560 HANDLE ConsoleHandle
,
561 BOOL CreateNewHandlesTable
,
562 PHANDLE pInputHandle
,
563 PHANDLE pOutputHandle
,
564 PHANDLE pErrorHandle
)
566 NTSTATUS Status
= STATUS_SUCCESS
;
569 /* Validate and lock the console */
570 if (!ConDrvValidateConsole(&Console
,
572 CONSOLE_RUNNING
, TRUE
))
574 // FIXME: Find another status code
575 return STATUS_UNSUCCESSFUL
;
578 /* Inherit the console */
579 ProcessData
->ConsoleHandle
= ConsoleHandle
;
581 if (CreateNewHandlesTable
)
584 * We are about to create a new console. However when ConSrvNewProcess
585 * was called, we didn't know that we wanted to create a new console and
586 * therefore, we by default inherited the handles table from our parent
587 * process. It's only now that we notice that in fact we do not need
588 * them, because we've created a new console and thus we must use it.
590 * Therefore, free the handles table so that we can recreate
591 * a new one later on.
593 ConSrvFreeHandlesTable(ProcessData
);
595 /* Initialize the handles table */
596 Status
= ConSrvInitHandlesTable(ProcessData
,
601 if (!NT_SUCCESS(Status
))
603 DPRINT1("Failed to initialize the handles table\n");
604 ProcessData
->ConsoleHandle
= NULL
;
609 /* Duplicate the Input Event */
610 Status
= NtDuplicateObject(NtCurrentProcess(),
611 Console
->InputBuffer
.ActiveEvent
,
612 ProcessData
->Process
->ProcessHandle
,
613 &ProcessData
->ConsoleEvent
,
614 EVENT_ALL_ACCESS
, 0, 0);
615 if (!NT_SUCCESS(Status
))
617 DPRINT1("NtDuplicateObject() failed: %lu\n", Status
);
618 ConSrvFreeHandlesTable(ProcessData
); // NOTE: Always free the handles table.
619 ProcessData
->ConsoleHandle
= NULL
;
623 /* Insert the process into the processes list of the console */
624 InsertHeadList(&Console
->ProcessList
, &ProcessData
->ConsoleLink
);
626 /* Add a reference count because the process is tied to the console */
627 _InterlockedIncrement(&Console
->ReferenceCount
);
629 /* Update the internal info of the terminal */
630 ConioRefreshInternalInfo(Console
);
632 Status
= STATUS_SUCCESS
;
635 /* Unlock the console and return */
636 LeaveCriticalSection(&Console
->Lock
);
642 ConSrvRemoveConsole(PCONSOLE_PROCESS_DATA ProcessData
)
646 DPRINT("ConSrvRemoveConsole\n");
648 // RtlEnterCriticalSection(&ProcessData->HandleTableLock);
650 /* Validate and lock the console */
651 if (ConDrvValidateConsole(&Console
,
652 ProcessData
->ConsoleHandle
,
653 CONSOLE_RUNNING
, TRUE
))
655 DPRINT("ConSrvRemoveConsole - Locking OK\n");
657 /* Close all console handles and free the handles table */
658 ConSrvFreeHandlesTable(ProcessData
);
660 /* Detach the process from the console */
661 ProcessData
->ConsoleHandle
= NULL
;
663 /* Remove ourselves from the console's list of processes */
664 RemoveEntryList(&ProcessData
->ConsoleLink
);
666 /* Update the internal info of the terminal */
667 ConioRefreshInternalInfo(Console
);
669 /* Release the console */
670 DPRINT("ConSrvRemoveConsole - Decrement Console->ReferenceCount = %lu\n", Console
->ReferenceCount
);
671 ConDrvReleaseConsole(Console
, TRUE
);
672 //CloseHandle(ProcessData->ConsoleEvent);
673 //ProcessData->ConsoleEvent = NULL;
676 // RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
680 /* PUBLIC SERVER APIS *********************************************************/
682 CSR_API(SrvOpenConsole
)
685 * This API opens a handle to either the input buffer or to
686 * a screen-buffer of the console of the current process.
690 PCONSOLE_OPENCONSOLE OpenConsoleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.OpenConsoleRequest
;
691 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
694 DWORD DesiredAccess
= OpenConsoleRequest
->Access
;
695 DWORD ShareMode
= OpenConsoleRequest
->ShareMode
;
696 PCONSOLE_IO_OBJECT Object
;
698 OpenConsoleRequest
->ConsoleHandle
= INVALID_HANDLE_VALUE
;
700 Status
= ConSrvGetConsole(ProcessData
, &Console
, TRUE
);
701 if (!NT_SUCCESS(Status
))
703 DPRINT1("Can't get console\n");
707 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
710 * Open a handle to either the active screen buffer or the input buffer.
712 if (OpenConsoleRequest
->HandleType
== HANDLE_OUTPUT
)
714 Object
= &Console
->ActiveBuffer
->Header
;
718 Object
= &Console
->InputBuffer
.Header
;
721 if (((DesiredAccess
& GENERIC_READ
) && Object
->ExclusiveRead
!= 0) ||
722 ((DesiredAccess
& GENERIC_WRITE
) && Object
->ExclusiveWrite
!= 0) ||
723 (!(ShareMode
& FILE_SHARE_READ
) && Object
->AccessRead
!= 0) ||
724 (!(ShareMode
& FILE_SHARE_WRITE
) && Object
->AccessWrite
!= 0))
726 DPRINT1("Sharing violation\n");
727 Status
= STATUS_SHARING_VIOLATION
;
731 Status
= ConSrvInsertObject(ProcessData
,
732 &OpenConsoleRequest
->ConsoleHandle
,
735 OpenConsoleRequest
->Inheritable
,
739 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
741 ConSrvReleaseConsole(Console
, TRUE
);
745 CSR_API(SrvCloseHandle
)
748 PCONSOLE_CLOSEHANDLE CloseHandleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.CloseHandleRequest
;
749 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
752 Status
= ConSrvGetConsole(ProcessData
, &Console
, TRUE
);
753 if (!NT_SUCCESS(Status
))
755 DPRINT1("Can't get console\n");
759 Status
= ConSrvRemoveObject(ProcessData
, CloseHandleRequest
->ConsoleHandle
);
761 ConSrvReleaseConsole(Console
, TRUE
);
765 CSR_API(SrvVerifyConsoleIoHandle
)
768 PCONSOLE_VERIFYHANDLE VerifyHandleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.VerifyHandleRequest
;
769 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
772 HANDLE ConsoleHandle
= VerifyHandleRequest
->ConsoleHandle
;
773 ULONG Index
= HandleToULong(ConsoleHandle
) >> 2;
775 Status
= ConSrvGetConsole(ProcessData
, &Console
, TRUE
);
776 if (!NT_SUCCESS(Status
))
778 DPRINT1("Can't get console\n");
782 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
784 if (!IsConsoleHandle(ConsoleHandle
) ||
785 Index
>= ProcessData
->HandleTableSize
||
786 ProcessData
->HandleTable
[Index
].Object
== NULL
)
788 DPRINT("SrvVerifyConsoleIoHandle failed\n");
789 Status
= STATUS_INVALID_HANDLE
;
792 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
794 ConSrvReleaseConsole(Console
, TRUE
);
798 CSR_API(SrvDuplicateHandle
)
801 PCONSOLE_DUPLICATEHANDLE DuplicateHandleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.DuplicateHandleRequest
;
802 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
805 HANDLE ConsoleHandle
= DuplicateHandleRequest
->ConsoleHandle
;
806 ULONG Index
= HandleToULong(ConsoleHandle
) >> 2;
807 PCONSOLE_IO_HANDLE Entry
;
810 Status
= ConSrvGetConsole(ProcessData
, &Console
, TRUE
);
811 if (!NT_SUCCESS(Status
))
813 DPRINT1("Can't get console\n");
817 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
819 if ( /** !IsConsoleHandle(ConsoleHandle) || **/
820 Index
>= ProcessData
->HandleTableSize
||
821 (Entry
= &ProcessData
->HandleTable
[Index
])->Object
== NULL
)
823 DPRINT1("Couldn't duplicate invalid handle %p\n", ConsoleHandle
);
824 Status
= STATUS_INVALID_HANDLE
;
828 if (DuplicateHandleRequest
->Options
& DUPLICATE_SAME_ACCESS
)
830 DesiredAccess
= Entry
->Access
;
834 DesiredAccess
= DuplicateHandleRequest
->Access
;
835 /* Make sure the source handle has all the desired flags */
836 if ((Entry
->Access
& DesiredAccess
) == 0)
838 DPRINT1("Handle %p only has access %X; requested %X\n",
839 ConsoleHandle
, Entry
->Access
, DesiredAccess
);
840 Status
= STATUS_INVALID_PARAMETER
;
845 /* Insert the new handle inside the process handles table */
846 Status
= ConSrvInsertObject(ProcessData
,
847 &DuplicateHandleRequest
->ConsoleHandle
, // Use the new handle value!
850 DuplicateHandleRequest
->Inheritable
,
852 if (NT_SUCCESS(Status
) &&
853 (DuplicateHandleRequest
->Options
& DUPLICATE_CLOSE_SOURCE
))
855 /* Close the original handle if needed */
856 ConSrvCloseHandleEntry(Entry
);
860 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
862 ConSrvReleaseConsole(Console
, TRUE
);