ReactOS  0.4.13-dev-464-g6b95727
handle.c
Go to the documentation of this file.
1 /*
2  * LICENSE: GPL - See COPYING in the top level directory
3  * PROJECT: ReactOS Console Server DLL
4  * FILE: win32ss/user/winsrv/consrv_new/handle.c
5  * PURPOSE: Console I/O Handles functions
6  * PROGRAMMERS: David Welch
7  * Jeffrey Morlan
8  * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
9  */
10 
11 /* INCLUDES *******************************************************************/
12 
13 #include "consrv.h"
14 #include "include/conio.h"
15 #include "include/conio2.h"
16 #include "handle.h"
17 #include "include/console.h"
18 #include "console.h"
19 #include "conoutput.h"
20 
21 #define NDEBUG
22 #include <debug.h>
23 
24 
25 /* GLOBALS ********************************************************************/
26 
27 typedef struct _CONSOLE_IO_HANDLE
28 {
29  PCONSOLE_IO_OBJECT Object; /* The object on which the handle points to */
34 
35 
36 /* PRIVATE FUNCTIONS **********************************************************/
37 
38 static INT
40 {
42 
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);
45 
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;
50 
51  Object->HandleCount += Change;
52 
53  return Object->HandleCount;
54 }
55 
56 static VOID
58 {
63 }
64 
65 static VOID
67 {
69  if (Object != NULL)
70  {
73 
74  /*
75  * If this is a input handle, notify and dereference
76  * all the waits related to this handle.
77  */
78  if (Object->Type == INPUT_BUFFER)
79  {
81 
82  /*
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
85  * from the list.
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
89  * return.
90  */
91  CsrNotifyWait(&InputBuffer->ReadWaitQueue,
92  WaitAll,
93  NULL,
94  (PVOID)Entry);
95  if (!IsListEmpty(&InputBuffer->ReadWaitQueue))
96  {
97  CsrDereferenceWait(&InputBuffer->ReadWaitQueue);
98  }
99  }
100 
101  /* If the last handle to a screen buffer is closed, delete it... */
102  if (AdjustHandleCounts(Entry, -1) == 0)
103  {
104  if (Object->Type == TEXTMODE_BUFFER || Object->Type == GRAPHICS_BUFFER)
105  {
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)
112  }
113  else if (Object->Type == INPUT_BUFFER)
114  {
115  DPRINT("Closing the input buffer\n");
116  }
117  else
118  {
119  DPRINT1("Invalid object type %d\n", Object->Type);
120  }
121  }
122 
124 
125  /* Invalidate (zero-out) this handle entry */
126  // Entry->Object = NULL;
127  // RtlZeroMemory(Entry, sizeof(*Entry));
128  }
129  RtlZeroMemory(Entry, sizeof(*Entry)); // Be sure the whole entry is invalidated.
130 }
131 
132 
133 /* Forward declaration, used in ConSrvInitHandlesTable */
135 
136 static NTSTATUS
139  OUT PHANDLE pInputHandle,
140  OUT PHANDLE pOutputHandle,
141  OUT PHANDLE pErrorHandle)
142 {
146  ErrorHandle = INVALID_HANDLE_VALUE;
147 
148  /*
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.
152  *
153  * Insert the IO handles.
154  */
155 
156  RtlEnterCriticalSection(&ProcessData->HandleTableLock);
157 
158  /* Insert the Input handle */
159  Status = ConSrvInsertObject(ProcessData,
160  &InputHandle,
161  &Console->InputBuffer.Header,
163  TRUE,
165  if (!NT_SUCCESS(Status))
166  {
167  DPRINT1("Failed to insert the input handle\n");
168  RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
169  ConSrvFreeHandlesTable(ProcessData);
170  return Status;
171  }
172 
173  /* Insert the Output handle */
174  Status = ConSrvInsertObject(ProcessData,
175  &OutputHandle,
176  &Console->ActiveBuffer->Header,
178  TRUE,
180  if (!NT_SUCCESS(Status))
181  {
182  DPRINT1("Failed to insert the output handle\n");
183  RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
184  ConSrvFreeHandlesTable(ProcessData);
185  return Status;
186  }
187 
188  /* Insert the Error handle */
189  Status = ConSrvInsertObject(ProcessData,
190  &ErrorHandle,
191  &Console->ActiveBuffer->Header,
193  TRUE,
195  if (!NT_SUCCESS(Status))
196  {
197  DPRINT1("Failed to insert the error handle\n");
198  RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
199  ConSrvFreeHandlesTable(ProcessData);
200  return Status;
201  }
202 
203  /* Return the newly created handles */
204  *pInputHandle = InputHandle;
205  *pOutputHandle = OutputHandle;
206  *pErrorHandle = ErrorHandle;
207 
208  RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
209  return STATUS_SUCCESS;
210 }
211 
212 NTSTATUS
214  IN PCONSOLE_PROCESS_DATA TargetProcessData)
215 {
217  ULONG i, j;
218 
219  RtlEnterCriticalSection(&SourceProcessData->HandleTableLock);
220 
221  /* Inherit a handles table only if there is no already */
222  if (TargetProcessData->HandleTable != NULL /* || TargetProcessData->HandleTableSize != 0 */)
223  {
225  goto Quit;
226  }
227 
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)
233  {
235  goto Quit;
236  }
237 
238  TargetProcessData->HandleTableSize = SourceProcessData->HandleTableSize;
239 
240  /*
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.
243  */
244  for (i = 0, j = 0; i < SourceProcessData->HandleTableSize; i++)
245  {
246  if (SourceProcessData->HandleTable[i].Object != NULL &&
247  SourceProcessData->HandleTable[i].Inheritable)
248  {
249  /*
250  * Copy the handle data and increment the reference count of the
251  * pointed object (via the call to ConSrvCreateHandleEntry).
252  */
253  TargetProcessData->HandleTable[j] = SourceProcessData->HandleTable[i];
254  ConSrvCreateHandleEntry(&TargetProcessData->HandleTable[j]);
255  ++j;
256  }
257  }
258 
259 Quit:
260  RtlLeaveCriticalSection(&SourceProcessData->HandleTableLock);
261  return Status;
262 }
263 
264 static VOID
266 {
268 
269  if (ProcessData->HandleTable != NULL)
270  {
271  ULONG i;
272 
273  /*
274  * ProcessData->ConsoleHandle is NULL (and the assertion fails) when
275  * ConSrvFreeHandlesTable is called in ConSrvConnect during the
276  * allocation of a new console.
277  */
278  // ASSERT(ProcessData->ConsoleHandle);
279  if (ProcessData->ConsoleHandle != NULL)
280  {
281  /* Close all the console handles */
282  for (i = 0; i < ProcessData->HandleTableSize; i++)
283  {
284  ConSrvCloseHandleEntry(&ProcessData->HandleTable[i]);
285  }
286  }
287  /* Free the handles table memory */
288  ConsoleFreeHeap(ProcessData->HandleTable);
289  ProcessData->HandleTable = NULL;
290  }
291 
292  ProcessData->HandleTableSize = 0;
293 
295 }
296 
297 VOID
298 FASTCALL
302 {
303  ASSERT(Object);
304  // if (!Object) return;
305 
306  Object->Type = Type;
307  Object->Console = Console;
308  Object->AccessRead = Object->AccessWrite = 0;
309  Object->ExclusiveRead = Object->ExclusiveWrite = 0;
310  Object->HandleCount = 0;
311 }
312 
313 NTSTATUS
314 FASTCALL
316  PHANDLE Handle,
318  DWORD Access,
319  BOOL Inheritable,
320  DWORD ShareMode)
321 {
322 #define IO_HANDLES_INCREMENT 2 * 3
323 
324  ULONG i = 0;
325  PCONSOLE_IO_HANDLE Block;
326 
327  // NOTE: Commented out because calling code always lock HandleTableLock before.
328  // RtlEnterCriticalSection(&ProcessData->HandleTableLock);
329 
330  ASSERT( (ProcessData->HandleTable == NULL && ProcessData->HandleTableSize == 0) ||
331  (ProcessData->HandleTable != NULL && ProcessData->HandleTableSize != 0) );
332 
333  if (ProcessData->HandleTable)
334  {
335  for (i = 0; i < ProcessData->HandleTableSize; i++)
336  {
337  if (ProcessData->HandleTable[i].Object == NULL)
338  break;
339  }
340  }
341 
342  if (i >= ProcessData->HandleTableSize)
343  {
344  /* Allocate a new handles table */
346  (ProcessData->HandleTableSize +
348  if (Block == NULL)
349  {
350  // RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
351  return STATUS_UNSUCCESSFUL;
352  }
353 
354  /* If we previously had a handles table, free it and use the new one */
355  if (ProcessData->HandleTable)
356  {
357  /* Copy the handles from the old table to the new one */
358  RtlCopyMemory(Block,
359  ProcessData->HandleTable,
360  ProcessData->HandleTableSize * sizeof(CONSOLE_IO_HANDLE));
361  ConsoleFreeHeap(ProcessData->HandleTable);
362  }
363  ProcessData->HandleTable = Block;
364  ProcessData->HandleTableSize += IO_HANDLES_INCREMENT;
365  }
366 
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);
373 
374  // RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
375 
376  return STATUS_SUCCESS;
377 }
378 
379 NTSTATUS
380 FASTCALL
382  HANDLE Handle)
383 {
386 
388 
389  ASSERT(ProcessData->HandleTable);
390 
391  if (Index >= ProcessData->HandleTableSize ||
392  (Object = ProcessData->HandleTable[Index].Object) == NULL)
393  {
395  return STATUS_INVALID_HANDLE;
396  }
397 
398  ASSERT(ProcessData->ConsoleHandle);
399  ConSrvCloseHandleEntry(&ProcessData->HandleTable[Index]);
400 
402  return STATUS_SUCCESS;
403 }
404 
405 NTSTATUS
406 FASTCALL
408  HANDLE Handle,
411  DWORD Access,
412  BOOL LockConsole,
414 {
415  // NTSTATUS Status;
417  PCONSOLE_IO_HANDLE HandleEntry = NULL;
418  PCONSOLE_IO_OBJECT ObjectEntry = NULL;
419  // PCONSOLE ObjectConsole;
420 
421  ASSERT(Object);
422  if (Entry) *Entry = NULL;
423 
424  DPRINT("ConSrvGetObject -- Object: 0x%x, Handle: 0x%x\n", Object, Handle);
425 
427 
428  if ( IsConsoleHandle(Handle) &&
429  Index < ProcessData->HandleTableSize )
430  {
431  HandleEntry = &ProcessData->HandleTable[Index];
432  ObjectEntry = HandleEntry->Object;
433  }
434 
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) )
440  {
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));
443 
445  return STATUS_INVALID_HANDLE;
446  }
447 
449 
450  // Status = ConDrvGetConsole(&ObjectConsole, ProcessData->ConsoleHandle, LockConsole);
451  // if (NT_SUCCESS(Status))
452  if (ConDrvValidateConsoleUnsafe(ObjectEntry->Console, CONSOLE_RUNNING, LockConsole))
453  {
454  _InterlockedIncrement(&ObjectEntry->Console->ReferenceCount);
455 
456  /* Return the objects to the caller */
457  *Object = ObjectEntry;
458  if (Entry) *Entry = HandleEntry;
459 
460  // RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
461  return STATUS_SUCCESS;
462  }
463  else
464  {
465  // RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
466  return STATUS_INVALID_HANDLE;
467  }
468 }
469 
470 VOID
471 FASTCALL
473  BOOL IsConsoleLocked)
474 {
475  ConSrvReleaseConsole(Object->Console, IsConsoleLocked);
476 }
477 
478 NTSTATUS
479 FASTCALL
481  PHANDLE pInputHandle,
482  PHANDLE pOutputHandle,
483  PHANDLE pErrorHandle,
484  PCONSOLE_START_INFO ConsoleStartInfo)
485 {
487  HANDLE ConsoleHandle;
489 
490  /*
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.
496  *
497  * Therefore, free the handles table so that we can recreate
498  * a new one later on.
499  */
500  ConSrvFreeHandlesTable(ProcessData);
501 
502  /* Initialize a new Console owned by this process */
503  Status = ConSrvInitConsole(&ConsoleHandle,
504  &Console,
505  ConsoleStartInfo,
507  if (!NT_SUCCESS(Status))
508  {
509  DPRINT1("Console initialization failed\n");
510  return Status;
511  }
512 
513  /* Assign the new console handle */
514  ProcessData->ConsoleHandle = ConsoleHandle;
515 
516  /* Initialize the handles table */
517  Status = ConSrvInitHandlesTable(ProcessData,
518  Console,
519  pInputHandle,
520  pOutputHandle,
521  pErrorHandle);
522  if (!NT_SUCCESS(Status))
523  {
524  DPRINT1("Failed to initialize the handles table\n");
526  ProcessData->ConsoleHandle = NULL;
527  return Status;
528  }
529 
530  /* Duplicate the Input Event */
532  Console->InputBuffer.ActiveEvent,
533  ProcessData->Process->ProcessHandle,
534  &ProcessData->ConsoleEvent,
535  EVENT_ALL_ACCESS, 0, 0);
536  if (!NT_SUCCESS(Status))
537  {
538  DPRINT1("NtDuplicateObject() failed: %lu\n", Status);
539  ConSrvFreeHandlesTable(ProcessData);
541  ProcessData->ConsoleHandle = NULL;
542  return Status;
543  }
544 
545  /* Insert the process into the processes list of the console */
546  InsertHeadList(&Console->ProcessList, &ProcessData->ConsoleLink);
547 
548  /* Add a reference count because the process is tied to the console */
549  _InterlockedIncrement(&Console->ReferenceCount);
550 
551  /* Update the internal info of the terminal */
553 
554  return STATUS_SUCCESS;
555 }
556 
557 NTSTATUS
558 FASTCALL
560  HANDLE ConsoleHandle,
561  BOOL CreateNewHandlesTable,
562  PHANDLE pInputHandle,
563  PHANDLE pOutputHandle,
564  PHANDLE pErrorHandle)
565 {
568 
569  /* Validate and lock the console */
571  ConsoleHandle,
573  {
574  // FIXME: Find another status code
575  return STATUS_UNSUCCESSFUL;
576  }
577 
578  /* Inherit the console */
579  ProcessData->ConsoleHandle = ConsoleHandle;
580 
581  if (CreateNewHandlesTable)
582  {
583  /*
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.
589  *
590  * Therefore, free the handles table so that we can recreate
591  * a new one later on.
592  */
593  ConSrvFreeHandlesTable(ProcessData);
594 
595  /* Initialize the handles table */
596  Status = ConSrvInitHandlesTable(ProcessData,
597  Console,
598  pInputHandle,
599  pOutputHandle,
600  pErrorHandle);
601  if (!NT_SUCCESS(Status))
602  {
603  DPRINT1("Failed to initialize the handles table\n");
604  ProcessData->ConsoleHandle = NULL;
605  goto Quit;
606  }
607  }
608 
609  /* Duplicate the Input Event */
611  Console->InputBuffer.ActiveEvent,
612  ProcessData->Process->ProcessHandle,
613  &ProcessData->ConsoleEvent,
614  EVENT_ALL_ACCESS, 0, 0);
615  if (!NT_SUCCESS(Status))
616  {
617  DPRINT1("NtDuplicateObject() failed: %lu\n", Status);
618  ConSrvFreeHandlesTable(ProcessData); // NOTE: Always free the handles table.
619  ProcessData->ConsoleHandle = NULL;
620  goto Quit;
621  }
622 
623  /* Insert the process into the processes list of the console */
624  InsertHeadList(&Console->ProcessList, &ProcessData->ConsoleLink);
625 
626  /* Add a reference count because the process is tied to the console */
627  _InterlockedIncrement(&Console->ReferenceCount);
628 
629  /* Update the internal info of the terminal */
631 
633 
634 Quit:
635  /* Unlock the console and return */
637  return Status;
638 }
639 
640 VOID
641 FASTCALL
643 {
645 
646  DPRINT("ConSrvRemoveConsole\n");
647 
648  // RtlEnterCriticalSection(&ProcessData->HandleTableLock);
649 
650  /* Validate and lock the console */
652  ProcessData->ConsoleHandle,
654  {
655  DPRINT("ConSrvRemoveConsole - Locking OK\n");
656 
657  /* Close all console handles and free the handles table */
658  ConSrvFreeHandlesTable(ProcessData);
659 
660  /* Detach the process from the console */
661  ProcessData->ConsoleHandle = NULL;
662 
663  /* Remove ourselves from the console's list of processes */
664  RemoveEntryList(&ProcessData->ConsoleLink);
665 
666  /* Update the internal info of the terminal */
668 
669  /* Release the console */
670  DPRINT("ConSrvRemoveConsole - Decrement Console->ReferenceCount = %lu\n", Console->ReferenceCount);
672  //CloseHandle(ProcessData->ConsoleEvent);
673  //ProcessData->ConsoleEvent = NULL;
674  }
675 
676  // RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
677 }
678 
679 
680 /* PUBLIC SERVER APIS *********************************************************/
681 
682 CSR_API(SrvOpenConsole)
683 {
684  /*
685  * This API opens a handle to either the input buffer or to
686  * a screen-buffer of the console of the current process.
687  */
688 
690  PCONSOLE_OPENCONSOLE OpenConsoleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.OpenConsoleRequest;
693 
694  DWORD DesiredAccess = OpenConsoleRequest->Access;
695  DWORD ShareMode = OpenConsoleRequest->ShareMode;
697 
698  OpenConsoleRequest->ConsoleHandle = INVALID_HANDLE_VALUE;
699 
700  Status = ConSrvGetConsole(ProcessData, &Console, TRUE);
701  if (!NT_SUCCESS(Status))
702  {
703  DPRINT1("Can't get console, status %lx\n", Status);
704  return Status;
705  }
706 
708 
709  /*
710  * Open a handle to either the active screen buffer or the input buffer.
711  */
712  if (OpenConsoleRequest->HandleType == HANDLE_OUTPUT)
713  {
714  Object = &Console->ActiveBuffer->Header;
715  }
716  else // HANDLE_INPUT
717  {
718  Object = &Console->InputBuffer.Header;
719  }
720 
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))
725  {
726  DPRINT1("Sharing violation\n");
728  }
729  else
730  {
731  Status = ConSrvInsertObject(ProcessData,
732  &OpenConsoleRequest->ConsoleHandle,
733  Object,
735  OpenConsoleRequest->Inheritable,
736  ShareMode);
737  }
738 
740 
742  return Status;
743 }
744 
745 CSR_API(SrvCloseHandle)
746 {
748  PCONSOLE_CLOSEHANDLE CloseHandleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.CloseHandleRequest;
751 
752  Status = ConSrvGetConsole(ProcessData, &Console, TRUE);
753  if (!NT_SUCCESS(Status))
754  {
755  DPRINT1("Can't get console, status %lx\n", Status);
756  return Status;
757  }
758 
759  Status = ConSrvRemoveObject(ProcessData, CloseHandleRequest->ConsoleHandle);
760 
762  return Status;
763 }
764 
765 CSR_API(SrvVerifyConsoleIoHandle)
766 {
768  PCONSOLE_VERIFYHANDLE VerifyHandleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.VerifyHandleRequest;
771 
772  HANDLE ConsoleHandle = VerifyHandleRequest->ConsoleHandle;
773  ULONG Index = HandleToULong(ConsoleHandle) >> 2;
774 
775  Status = ConSrvGetConsole(ProcessData, &Console, TRUE);
776  if (!NT_SUCCESS(Status))
777  {
778  DPRINT1("Can't get console, status %lx\n", Status);
779  return Status;
780  }
781 
783 
784  if (!IsConsoleHandle(ConsoleHandle) ||
785  Index >= ProcessData->HandleTableSize ||
786  ProcessData->HandleTable[Index].Object == NULL)
787  {
788  DPRINT("SrvVerifyConsoleIoHandle failed\n");
790  }
791 
793 
795  return Status;
796 }
797 
798 CSR_API(SrvDuplicateHandle)
799 {
801  PCONSOLE_DUPLICATEHANDLE DuplicateHandleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.DuplicateHandleRequest;
804 
805  HANDLE ConsoleHandle = DuplicateHandleRequest->ConsoleHandle;
806  ULONG Index = HandleToULong(ConsoleHandle) >> 2;
809 
810  Status = ConSrvGetConsole(ProcessData, &Console, TRUE);
811  if (!NT_SUCCESS(Status))
812  {
813  DPRINT1("Can't get console, status %lx\n", Status);
814  return Status;
815  }
816 
818 
819  if (
820  Index >= ProcessData->HandleTableSize ||
821  (Entry = &ProcessData->HandleTable[Index])->Object == NULL)
822  {
823  DPRINT1("Couldn't duplicate invalid handle %p\n", ConsoleHandle);
825  goto Quit;
826  }
827 
828  if (DuplicateHandleRequest->Options & DUPLICATE_SAME_ACCESS)
829  {
830  DesiredAccess = Entry->Access;
831  }
832  else
833  {
834  DesiredAccess = DuplicateHandleRequest->Access;
835  /* Make sure the source handle has all the desired flags */
836  if ((Entry->Access & DesiredAccess) == 0)
837  {
838  DPRINT1("Handle %p only has access %X; requested %X\n",
839  ConsoleHandle, Entry->Access, DesiredAccess);
841  goto Quit;
842  }
843  }
844 
845  /* Insert the new handle inside the process handles table */
846  Status = ConSrvInsertObject(ProcessData,
847  &DuplicateHandleRequest->ConsoleHandle, // Use the new handle value!
848  Entry->Object,
850  DuplicateHandleRequest->Inheritable,
851  Entry->ShareMode);
852  if (NT_SUCCESS(Status) &&
853  (DuplicateHandleRequest->Options & DUPLICATE_CLOSE_SOURCE))
854  {
855  /* Close the original handle if needed */
857  }
858 
859 Quit:
861 
863  return Status;
864 }
865 
866 /* EOF */
static INT AdjustHandleCounts(PCONSOLE_IO_HANDLE Entry, INT Change)
Definition: handle.c:39
HANDLE ConsoleHandle
Definition: consrv.h:45
#define IN
Definition: typedefs.h:38
#define DUPLICATE_CLOSE_SOURCE
#define ULongToHandle(h)
Definition: basetsd.h:81
NTSTATUS ConSrvGetConsole(IN PCONSOLE_PROCESS_DATA ProcessData, OUT PCONSRV_CONSOLE *Console, IN BOOLEAN LockConsole)
Definition: console.c:271
#define CsrGetClientThread()
Definition: csrsrv.h:77
CONSOLE_HANDLE_TYPE HandleType
Definition: conmsg.h:674
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
BOOL Inheritable
Definition: handle.c:31
struct _CONSOLE * Console
Definition: conio.h:52
HANDLE OutputHandle
Definition: apc.c:8
Type
Definition: Type.h:6
struct _Entry Entry
Definition: kefuncs.h:640
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
struct _CONSOLE_API_MESSAGE * PCONSOLE_API_MESSAGE
LONG NTSTATUS
Definition: precomp.h:26
#define HandleToUlong(h)
Definition: basetsd.h:79
#define ConsoleAllocHeap(Flags, Size)
Definition: heap.h:14
NTSYSAPI NTSTATUS NTAPI RtlEnterCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
#define HandleToULong(h)
Definition: basetsd.h:95
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define TEXTMODE_BUFFER
Definition: pccons.c:21
HANDLE UniqueProcess
Definition: compat.h:474
#define FASTCALL
Definition: nt_native.h:50
VOID ConSrvReleaseConsole(IN PCONSRV_CONSOLE Console, IN BOOLEAN IsConsoleLocked)
Definition: console.c:296
int32_t INT
Definition: typedefs.h:56
VOID NTAPI ConDrvReleaseConsole(IN PCONSOLE Console, IN BOOLEAN WasConsoleLocked)
Definition: console.c:402
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
BOOLEAN NTAPI CsrNotifyWait(IN PLIST_ENTRY WaitList, IN BOOLEAN NotifyAll, IN PVOID WaitArgument1, IN PVOID WaitArgument2)
Definition: wait.c:388
NTSTATUS ConSrvInheritConsole(PCONSOLE_PROCESS_DATA ProcessData, HANDLE ConsoleHandle, BOOLEAN CreateNewHandlesTable, PHANDLE pInputHandle, PHANDLE pOutputHandle, PHANDLE pErrorHandle, PCONSOLE_START_INFO ConsoleStartInfo)
Definition: handle.c:605
NTSTATUS ConSrvRemoveObject(IN PCONSOLE_PROCESS_DATA ProcessData, IN HANDLE Handle)
Definition: handle.c:375
#define STATUS_INVALID_HANDLE
Definition: ntstatus.h:231
CHAR InputBuffer[80]
Definition: conmgr.c:33
#define FILE_SHARE_READ
Definition: compat.h:125
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
struct _CONSOLE_INPUT_BUFFER * PCONSOLE_INPUT_BUFFER
LIST_ENTRY ConsoleLink
Definition: consrv.h:42
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
long __cdecl _InterlockedIncrement(_Interlocked_operand_ long volatile *_Addend)
#define DUPLICATE_SAME_ACCESS
#define STATUS_SHARING_VIOLATION
Definition: udferr_usr.h:154
unsigned int BOOL
Definition: ntddk_ex.h:94
NTSYSAPI NTSTATUS NTAPI RtlLeaveCriticalSection(_In_ PRTL_CRITICAL_SECTION CriticalSection)
#define EVENT_ALL_ACCESS
Definition: isotest.c:82
#define GENERIC_WRITE
Definition: nt_native.h:90
static NTSTATUS ConSrvInitHandlesTable(IN OUT PCONSOLE_PROCESS_DATA ProcessData, IN PCONSOLE Console, OUT PHANDLE pInputHandle, OUT PHANDLE pOutputHandle, OUT PHANDLE pErrorHandle)
Definition: handle.c:137
HANDLE ConsoleHandle
Definition: conmsg.h:633
NTSTATUS ConSrvRemoveConsole(PCONSOLE_PROCESS_DATA ProcessData)
Definition: handle.c:735
HANDLE ProcessHandle
Definition: csrsrv.h:46
struct _CONSOLE_SCREEN_BUFFER * PCONSOLE_SCREEN_BUFFER
Definition: conio.h:70
HANDLE ConsoleHandle
Definition: conmsg.h:626
smooth NULL
Definition: ftsmooth.c:416
struct _CONSOLE_IO_HANDLE CONSOLE_IO_HANDLE
static VOID ConSrvCloseHandleEntry(PCONSOLE_IO_HANDLE Entry)
Definition: handle.c:66
void DPRINT(...)
Definition: polytest.cpp:61
Definition: bufpool.h:45
CLIENT_ID ClientId
Definition: csrsrv.h:38
#define NtCurrentProcess()
Definition: nt_native.h:1657
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
_In_ HANDLE Handle
Definition: extypes.h:390
NTSTATUS NTAPI ConSrvInitConsole(OUT PHANDLE NewConsoleHandle, OUT PCONSRV_CONSOLE *NewConsole, IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo, IN PCSR_PROCESS ConsoleLeaderProcess)
Definition: console.c:511
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define ConsoleGetPerProcessData(Process)
Definition: consrv.h:37
PCONSOLE_IO_OBJECT Object
Definition: handle.c:25
static const UCHAR Index[8]
Definition: usbohci.c:18
BOOLEAN NTAPI ConDrvValidateConsole(OUT PCONSOLE *Console, IN HANDLE ConsoleHandle, IN CONSOLE_STATE ExpectedState, IN BOOLEAN LockConsole)
Definition: console.c:336
unsigned long DWORD
Definition: ntddk_ex.h:95
PCSR_PROCESS Process
Definition: consrv.h:43
#define IsConsoleHandle(h)
Definition: console.h:14
static IUnknown Object
Definition: main.c:512
VOID NTAPI CsrDereferenceWait(IN PLIST_ENTRY WaitList)
Definition: wait.c:266
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
DWORD ShareMode
Definition: handle.c:32
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:414
#define GENERIC_READ
Definition: compat.h:124
VOID ConSrvInitObject(IN OUT PCONSOLE_IO_OBJECT Object, IN CONSOLE_IO_OBJECT_TYPE Type, IN PCONSOLE Console)
Definition: handle.c:294
CSR_API(SrvOpenConsole)
Definition: handle.c:811
#define IO_HANDLES_INCREMENT
Status
Definition: gdiplustypes.h:24
static VOID ConSrvFreeHandlesTable(PCONSOLE_PROCESS_DATA ProcessData)
Definition: handle.c:265
NTSTATUS ConSrvGetObject(IN PCONSOLE_PROCESS_DATA ProcessData, IN HANDLE Handle, OUT PCONSOLE_IO_OBJECT *Object, OUT PVOID *Entry OPTIONAL, IN ULONG Access, IN BOOLEAN LockConsole, IN CONSOLE_IO_OBJECT_TYPE Type)
Definition: handle.c:401
VOID WINAPI ConioDeleteScreenBuffer(PCONSOLE_SCREEN_BUFFER Buffer)
Definition: conoutput.c:113
HANDLE InputHandle
Definition: apc.c:9
HANDLE ConsoleEvent
Definition: consrv.h:62
struct _CONSOLE_IO_HANDLE * PCONSOLE_IO_HANDLE
BOOLEAN NTAPI ConDrvValidateConsoleUnsafe(IN PCONSOLE Console, IN CONSOLE_STATE ExpectedState, IN BOOLEAN LockConsole)
Definition: console.c:120
static VOID ConSrvCreateHandleEntry(PCONSOLE_IO_HANDLE Entry)
Definition: handle.c:57
_In_ PIO_STACK_LOCATION _Inout_ PFILE_OBJECT _Inout_ PVCB _Outptr_result_maybenull_ PDCB _In_ PDCB _In_ PDIRENT _In_ ULONG _In_ ULONG _In_ PUNICODE_STRING _In_ PACCESS_MASK DesiredAccess
Definition: create.c:4157
#define STATUS_NO_MEMORY
Definition: ntstatus.h:246
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
struct _CONSOLE_IO_HANDLE * HandleTable
Definition: consrv.h:50
#define ConioRefreshInternalInfo(Console)
Definition: conio2.h:26
VOID NTAPI ConSrvDeleteConsole(PCONSRV_CONSOLE Console)
Definition: console.c:771
CConsole Console
#define DPRINT1
Definition: precomp.h:8
NTSTATUS ConSrvAllocateConsole(PCONSOLE_PROCESS_DATA ProcessData, PHANDLE pInputHandle, PHANDLE pOutputHandle, PHANDLE pErrorHandle, PCONSOLE_INIT_INFO ConsoleInitInfo)
Definition: handle.c:474
#define ConsoleFreeHeap(HeapBase)
Definition: heap.h:15
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
NTSTATUS NTAPI NtDuplicateObject(IN HANDLE SourceProcessHandle, IN HANDLE SourceHandle, IN HANDLE TargetProcessHandle OPTIONAL, OUT PHANDLE TargetHandle OPTIONAL, IN ACCESS_MASK DesiredAccess, IN ULONG HandleAttributes, IN ULONG Options)
Definition: obhandle.c:3407
#define OUT
Definition: typedefs.h:39
CONSOLE_IO_OBJECT_TYPE Type
Definition: conio.h:50
VOID ConSrvReleaseObject(IN PCONSOLE_IO_OBJECT Object, IN BOOLEAN IsConsoleLocked)
Definition: handle.c:465
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
NTSTATUS ConSrvInsertObject(IN PCONSOLE_PROCESS_DATA ProcessData, OUT PHANDLE Handle, IN PCONSOLE_IO_OBJECT Object, IN ULONG Access, IN BOOLEAN Inheritable, IN ULONG ShareMode)
Definition: handle.c:310
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
ULONG HandleTableSize
Definition: consrv.h:49
HANDLE ConsoleHandle
Definition: conmsg.h:673
NTSTATUS ConSrvInheritHandlesTable(IN PCONSOLE_PROCESS_DATA SourceProcessData, IN PCONSOLE_PROCESS_DATA TargetProcessData)
Definition: handle.c:203
return STATUS_SUCCESS
Definition: btrfs.c:2777
enum _CONSOLE_IO_OBJECT_TYPE CONSOLE_IO_OBJECT_TYPE
base of all file and directory entries
Definition: entries.h:82
RTL_CRITICAL_SECTION HandleTableLock
Definition: consrv.h:48
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68