xref: /reactos/win32ss/user/winsrv/consrv/handle.c (revision c05df38e)
1 /*
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
7  *                  Jeffrey Morlan
8  *                  Hermes Belusca-Maito (hermes.belusca@sfr.fr)
9  */
10 
11 /* INCLUDES *******************************************************************/
12 
13 #include "consrv.h"
14 
15 #include <win/console.h>
16 
17 #define NDEBUG
18 #include <debug.h>
19 
20 /* GLOBALS ********************************************************************/
21 
22 /* Console handle */
23 typedef struct _CONSOLE_IO_HANDLE
24 {
25     PCONSOLE_IO_OBJECT Object;   /* The object on which the handle points to */
26     ULONG   Access;
27     ULONG   ShareMode;
28     BOOLEAN Inheritable;
29 } CONSOLE_IO_HANDLE, *PCONSOLE_IO_HANDLE;
30 
31 
32 /* PRIVATE FUNCTIONS **********************************************************/
33 
34 static LONG
AdjustHandleCounts(IN PCONSOLE_IO_HANDLE Handle,IN LONG Change)35 AdjustHandleCounts(IN PCONSOLE_IO_HANDLE Handle,
36                    IN LONG Change)
37 {
38     PCONSOLE_IO_OBJECT Object = Handle->Object;
39 
40     DPRINT("AdjustHandleCounts(0x%p, %d), Object = 0x%p\n",
41            Handle, Change, Object);
42     DPRINT("\tAdjustHandleCounts(0x%p, %d), Object = 0x%p, Object->ReferenceCount = %d, Object->Type = %lu\n",
43            Handle, Change, Object, Object->ReferenceCount, Object->Type);
44 
45     if (Handle->Access & GENERIC_READ)           Object->AccessRead += Change;
46     if (Handle->Access & GENERIC_WRITE)          Object->AccessWrite += Change;
47     if (!(Handle->ShareMode & FILE_SHARE_READ))  Object->ExclusiveRead += Change;
48     if (!(Handle->ShareMode & FILE_SHARE_WRITE)) Object->ExclusiveWrite += Change;
49 
50     Object->ReferenceCount += Change;
51 
52     return Object->ReferenceCount;
53 }
54 
55 static VOID
ConSrvCloseHandle(IN PCONSOLE_IO_HANDLE Handle)56 ConSrvCloseHandle(IN PCONSOLE_IO_HANDLE Handle)
57 {
58     PCONSOLE_IO_OBJECT Object = Handle->Object;
59     if (Object != NULL)
60     {
61         /*
62          * If this is a input handle, notify and dereference
63          * all the waits related to this handle.
64          */
65         if (Object->Type == INPUT_BUFFER)
66         {
67             // PCONSOLE_INPUT_BUFFER InputBuffer = (PCONSOLE_INPUT_BUFFER)Object;
68             PCONSRV_CONSOLE Console = (PCONSRV_CONSOLE)Object->Console;
69 
70             /*
71              * Wake up all the writing waiters related to this handle for this
72              * input buffer, if any, then dereference them and purge them all
73              * from the list.
74              * To select them amongst all the waiters for this input buffer,
75              * pass the handle pointer to the waiters, then they will check
76              * whether or not they are related to this handle and if so, they
77              * return.
78              */
79             CsrNotifyWait(&Console->ReadWaitQueue,
80                           TRUE,
81                           NULL,
82                           (PVOID)Handle);
83             if (!IsListEmpty(&Console->ReadWaitQueue))
84             {
85                 CsrDereferenceWait(&Console->ReadWaitQueue);
86             }
87         }
88 
89         /* If the last handle to a screen buffer is closed, delete it... */
90         if (AdjustHandleCounts(Handle, -1) == 0)
91         {
92             if (Object->Type == TEXTMODE_BUFFER || Object->Type == GRAPHICS_BUFFER)
93             {
94                 PCONSOLE_SCREEN_BUFFER Buffer = (PCONSOLE_SCREEN_BUFFER)Object;
95                 /* ...unless it's the only buffer left. Windows allows deletion
96                  * even of the last buffer, but having to deal with a lack of
97                  * any active buffer might be error-prone. */
98                 if (Buffer->ListEntry.Flink != Buffer->ListEntry.Blink)
99                     ConDrvDeleteScreenBuffer(Buffer);
100             }
101             else if (Object->Type == INPUT_BUFFER)
102             {
103                 DPRINT("Closing the input buffer\n");
104             }
105             else
106             {
107                 DPRINT1("Invalid object type %d\n", Object->Type);
108             }
109         }
110 
111         /* Invalidate (zero-out) this handle entry */
112         // Handle->Object = NULL;
113         // RtlZeroMemory(Handle, sizeof(*Handle));
114     }
115     RtlZeroMemory(Handle, sizeof(*Handle)); // Be sure the whole entry is invalidated.
116 }
117 
118 
119 NTSTATUS
ConSrvInheritHandlesTable(IN PCONSOLE_PROCESS_DATA SourceProcessData,IN PCONSOLE_PROCESS_DATA TargetProcessData)120 ConSrvInheritHandlesTable(IN PCONSOLE_PROCESS_DATA SourceProcessData,
121                           IN PCONSOLE_PROCESS_DATA TargetProcessData)
122 {
123     NTSTATUS Status = STATUS_SUCCESS;
124     ULONG i, j;
125 
126     RtlEnterCriticalSection(&SourceProcessData->HandleTableLock);
127 
128     /* Inherit a handles table only if there is no already */
129     if (TargetProcessData->HandleTable != NULL /* || TargetProcessData->HandleTableSize != 0 */)
130     {
131         Status = STATUS_UNSUCCESSFUL;
132         goto Quit;
133     }
134 
135     /* Allocate a new handle table for the child process */
136     TargetProcessData->HandleTable = ConsoleAllocHeap(HEAP_ZERO_MEMORY,
137                                                       SourceProcessData->HandleTableSize
138                                                         * sizeof(CONSOLE_IO_HANDLE));
139     if (TargetProcessData->HandleTable == NULL)
140     {
141         Status = STATUS_NO_MEMORY;
142         goto Quit;
143     }
144 
145     TargetProcessData->HandleTableSize = SourceProcessData->HandleTableSize;
146 
147     /*
148      * Parse the parent process' handles table and, for each handle,
149      * do a copy of it and reference it, if the handle is inheritable.
150      */
151     for (i = 0, j = 0; i < SourceProcessData->HandleTableSize; i++)
152     {
153         if (SourceProcessData->HandleTable[i].Object != NULL &&
154             SourceProcessData->HandleTable[i].Inheritable)
155         {
156             /*
157              * Copy the handle data and increment the reference count of the
158              * pointed object (via the call to ConSrvCreateHandleEntry == AdjustHandleCounts).
159              */
160             TargetProcessData->HandleTable[j] = SourceProcessData->HandleTable[i];
161             AdjustHandleCounts(&TargetProcessData->HandleTable[j], +1);
162             ++j;
163         }
164     }
165 
166 Quit:
167     RtlLeaveCriticalSection(&SourceProcessData->HandleTableLock);
168     return Status;
169 }
170 
171 VOID
ConSrvFreeHandlesTable(IN PCONSOLE_PROCESS_DATA ProcessData)172 ConSrvFreeHandlesTable(IN PCONSOLE_PROCESS_DATA ProcessData)
173 {
174     RtlEnterCriticalSection(&ProcessData->HandleTableLock);
175 
176     if (ProcessData->HandleTable != NULL)
177     {
178         ULONG i;
179 
180         /*
181          * ProcessData->ConsoleHandle is NULL (and the assertion fails) when
182          * ConSrvFreeHandlesTable is called in ConSrvConnect during the
183          * allocation of a new console.
184          */
185         // ASSERT(ProcessData->ConsoleHandle);
186         if (ProcessData->ConsoleHandle != NULL)
187         {
188             /* Close all the console handles */
189             for (i = 0; i < ProcessData->HandleTableSize; i++)
190             {
191                 ConSrvCloseHandle(&ProcessData->HandleTable[i]);
192             }
193         }
194         /* Free the handles table memory */
195         ConsoleFreeHeap(ProcessData->HandleTable);
196         ProcessData->HandleTable = NULL;
197     }
198 
199     ProcessData->HandleTableSize = 0;
200 
201     RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
202 }
203 
204 
205 
206 
207 
208 
209 // ConSrvCreateObject
210 VOID
ConSrvInitObject(IN OUT PCONSOLE_IO_OBJECT Object,IN CONSOLE_IO_OBJECT_TYPE Type,IN PCONSOLE Console)211 ConSrvInitObject(IN OUT PCONSOLE_IO_OBJECT Object,
212                  IN CONSOLE_IO_OBJECT_TYPE Type,
213                  IN PCONSOLE Console)
214 {
215     ASSERT(Object);
216     // if (!Object) return;
217 
218     Object->Type    = Type;
219     Object->Console = Console;
220     Object->ReferenceCount = 0;
221 
222     Object->AccessRead    = Object->AccessWrite    = 0;
223     Object->ExclusiveRead = Object->ExclusiveWrite = 0;
224 }
225 
226 NTSTATUS
ConSrvInsertObject(IN PCONSOLE_PROCESS_DATA ProcessData,OUT PHANDLE Handle,IN PCONSOLE_IO_OBJECT Object,IN ULONG Access,IN BOOLEAN Inheritable,IN ULONG ShareMode)227 ConSrvInsertObject(IN PCONSOLE_PROCESS_DATA ProcessData,
228                    OUT PHANDLE Handle,
229                    IN PCONSOLE_IO_OBJECT Object,
230                    IN ULONG Access,
231                    IN BOOLEAN Inheritable,
232                    IN ULONG ShareMode)
233 {
234 #define IO_HANDLES_INCREMENT    2 * 3
235 
236     ULONG i = 0;
237     PCONSOLE_IO_HANDLE Block;
238 
239     // NOTE: Commented out because calling code always lock HandleTableLock before.
240     // RtlEnterCriticalSection(&ProcessData->HandleTableLock);
241 
242     ASSERT( (ProcessData->HandleTable == NULL && ProcessData->HandleTableSize == 0) ||
243             (ProcessData->HandleTable != NULL && ProcessData->HandleTableSize != 0) );
244 
245     if (ProcessData->HandleTable)
246     {
247         for (i = 0; i < ProcessData->HandleTableSize; i++)
248         {
249             if (ProcessData->HandleTable[i].Object == NULL)
250                 break;
251         }
252     }
253 
254     if (i >= ProcessData->HandleTableSize)
255     {
256         /* Allocate a new handles table */
257         Block = ConsoleAllocHeap(HEAP_ZERO_MEMORY,
258                                  (ProcessData->HandleTableSize +
259                                     IO_HANDLES_INCREMENT) * sizeof(CONSOLE_IO_HANDLE));
260         if (Block == NULL)
261         {
262             // RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
263             return STATUS_UNSUCCESSFUL;
264         }
265 
266         /* If we previously had a handles table, free it and use the new one */
267         if (ProcessData->HandleTable)
268         {
269             /* Copy the handles from the old table to the new one */
270             RtlCopyMemory(Block,
271                           ProcessData->HandleTable,
272                           ProcessData->HandleTableSize * sizeof(CONSOLE_IO_HANDLE));
273             ConsoleFreeHeap(ProcessData->HandleTable);
274         }
275         ProcessData->HandleTable = Block;
276         ProcessData->HandleTableSize += IO_HANDLES_INCREMENT;
277     }
278 
279     ProcessData->HandleTable[i].Object      = Object;
280     ProcessData->HandleTable[i].Access      = Access;
281     ProcessData->HandleTable[i].Inheritable = Inheritable;
282     ProcessData->HandleTable[i].ShareMode   = ShareMode;
283     AdjustHandleCounts(&ProcessData->HandleTable[i], +1);
284     *Handle = ULongToHandle((i << 2) | 0x3);
285 
286     // RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
287 
288     return STATUS_SUCCESS;
289 }
290 
291 NTSTATUS
ConSrvRemoveObject(IN PCONSOLE_PROCESS_DATA ProcessData,IN HANDLE Handle)292 ConSrvRemoveObject(IN PCONSOLE_PROCESS_DATA ProcessData,
293                    IN HANDLE Handle)
294 {
295     ULONG Index = HandleToULong(Handle) >> 2;
296 
297     RtlEnterCriticalSection(&ProcessData->HandleTableLock);
298 
299     ASSERT(ProcessData->HandleTable);
300     // ASSERT( (ProcessData->HandleTable == NULL && ProcessData->HandleTableSize == 0) ||
301     //         (ProcessData->HandleTable != NULL && ProcessData->HandleTableSize != 0) );
302 
303     if (Index >= ProcessData->HandleTableSize ||
304         ProcessData->HandleTable[Index].Object == NULL)
305     {
306         RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
307         return STATUS_INVALID_HANDLE;
308     }
309 
310     ASSERT(ProcessData->ConsoleHandle);
311     ConSrvCloseHandle(&ProcessData->HandleTable[Index]);
312 
313     RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
314     return STATUS_SUCCESS;
315 }
316 
317 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)318 ConSrvGetObject(IN PCONSOLE_PROCESS_DATA ProcessData,
319                 IN HANDLE Handle,
320                 OUT PCONSOLE_IO_OBJECT* Object,
321                 OUT PVOID* Entry OPTIONAL,
322                 IN ULONG Access,
323                 IN BOOLEAN LockConsole,
324                 IN CONSOLE_IO_OBJECT_TYPE Type)
325 {
326     // NTSTATUS Status;
327     ULONG Index = HandleToULong(Handle) >> 2;
328     PCONSOLE_IO_HANDLE HandleEntry = NULL;
329     PCONSOLE_IO_OBJECT ObjectEntry = NULL;
330     // PCONSRV_CONSOLE ObjectConsole;
331 
332     ASSERT(Object);
333     if (Entry) *Entry = NULL;
334 
335     DPRINT("ConSrvGetObject -- Object: 0x%x, Handle: 0x%x\n", Object, Handle);
336 
337     RtlEnterCriticalSection(&ProcessData->HandleTableLock);
338 
339     if ( IsConsoleHandle(Handle) &&
340          Index < ProcessData->HandleTableSize )
341     {
342         HandleEntry = &ProcessData->HandleTable[Index];
343         ObjectEntry = HandleEntry->Object;
344     }
345 
346     if ( HandleEntry == NULL ||
347          ObjectEntry == NULL ||
348          (HandleEntry->Access & Access) == 0 ||
349          /*(Type != 0 && ObjectEntry->Type != Type)*/
350          (Type != 0 && (ObjectEntry->Type & Type) == 0) )
351     {
352         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",
353                Handle, Type, Access, ObjectEntry, HandleEntry, (ObjectEntry ? ObjectEntry->Type : 0), (HandleEntry ? HandleEntry->Access : 0));
354 
355         RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
356         return STATUS_INVALID_HANDLE;
357     }
358 
359     RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
360 
361     // Status = ConSrvGetConsole(ProcessData, &ObjectConsole, LockConsole);
362     // if (NT_SUCCESS(Status))
363     if (ConDrvValidateConsoleUnsafe(ObjectEntry->Console, CONSOLE_RUNNING, LockConsole))
364     {
365         _InterlockedIncrement(&ObjectEntry->Console->ReferenceCount);
366 
367         /* Return the objects to the caller */
368         *Object = ObjectEntry;
369         if (Entry) *Entry = HandleEntry;
370 
371         // RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
372         return STATUS_SUCCESS;
373     }
374     else
375     {
376         // RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
377         return STATUS_INVALID_HANDLE;
378     }
379 }
380 
381 VOID
ConSrvReleaseObject(IN PCONSOLE_IO_OBJECT Object,IN BOOLEAN IsConsoleLocked)382 ConSrvReleaseObject(IN PCONSOLE_IO_OBJECT Object,
383                     IN BOOLEAN IsConsoleLocked)
384 {
385     PCONSRV_CONSOLE ObjectConsole = (PCONSRV_CONSOLE)Object->Console;
386     ConSrvReleaseConsole(ObjectConsole, IsConsoleLocked);
387 }
388 
389 
390 /* PUBLIC SERVER APIS *********************************************************/
391 
392 /* API_NUMBER: ConsolepOpenConsole */
CON_API(SrvOpenConsole,CONSOLE_OPENCONSOLE,OpenConsoleRequest)393 CON_API(SrvOpenConsole,
394         CONSOLE_OPENCONSOLE, OpenConsoleRequest)
395 {
396     /*
397      * This API opens a handle to either the input buffer or to
398      * a screen-buffer of the console of the current process.
399      */
400 
401     NTSTATUS Status;
402     DWORD DesiredAccess = OpenConsoleRequest->DesiredAccess;
403     DWORD ShareMode = OpenConsoleRequest->ShareMode;
404     PCONSOLE_IO_OBJECT Object;
405 
406     OpenConsoleRequest->Handle = INVALID_HANDLE_VALUE;
407 
408     RtlEnterCriticalSection(&ProcessData->HandleTableLock);
409 
410     /*
411      * Open a handle to either the active screen buffer or the input buffer.
412      */
413     if (OpenConsoleRequest->HandleType == HANDLE_OUTPUT)
414     {
415         Object = &Console->ActiveBuffer->Header;
416     }
417     else // HANDLE_INPUT
418     {
419         Object = &Console->InputBuffer.Header;
420     }
421 
422     if (((DesiredAccess & GENERIC_READ)  && Object->ExclusiveRead  != 0) ||
423         ((DesiredAccess & GENERIC_WRITE) && Object->ExclusiveWrite != 0) ||
424         (!(ShareMode & FILE_SHARE_READ)  && Object->AccessRead     != 0) ||
425         (!(ShareMode & FILE_SHARE_WRITE) && Object->AccessWrite    != 0))
426     {
427         DPRINT1("Sharing violation\n");
428         Status = STATUS_SHARING_VIOLATION;
429     }
430     else
431     {
432         Status = ConSrvInsertObject(ProcessData,
433                                     &OpenConsoleRequest->Handle,
434                                     Object,
435                                     DesiredAccess,
436                                     OpenConsoleRequest->InheritHandle,
437                                     ShareMode);
438     }
439 
440     RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
441 
442     return Status;
443 }
444 
445 /* API_NUMBER: ConsolepDuplicateHandle */
CON_API(SrvDuplicateHandle,CONSOLE_DUPLICATEHANDLE,DuplicateHandleRequest)446 CON_API(SrvDuplicateHandle,
447         CONSOLE_DUPLICATEHANDLE, DuplicateHandleRequest)
448 {
449     NTSTATUS Status;
450     HANDLE SourceHandle = DuplicateHandleRequest->SourceHandle;
451     ULONG Index = HandleToULong(SourceHandle) >> 2;
452     PCONSOLE_IO_HANDLE Entry;
453     DWORD DesiredAccess;
454 
455     DuplicateHandleRequest->TargetHandle = INVALID_HANDLE_VALUE;
456 
457     RtlEnterCriticalSection(&ProcessData->HandleTableLock);
458 
459     // ASSERT( (ProcessData->HandleTable == NULL && ProcessData->HandleTableSize == 0) ||
460     //         (ProcessData->HandleTable != NULL && ProcessData->HandleTableSize != 0) );
461 
462     if ( /** !IsConsoleHandle(SourceHandle)   || **/
463         Index >= ProcessData->HandleTableSize ||
464         (Entry = &ProcessData->HandleTable[Index])->Object == NULL)
465     {
466         DPRINT1("Couldn't duplicate invalid handle 0x%p\n", SourceHandle);
467         Status = STATUS_INVALID_HANDLE;
468         goto Quit;
469     }
470 
471     if (DuplicateHandleRequest->Options & DUPLICATE_SAME_ACCESS)
472     {
473         DesiredAccess = Entry->Access;
474     }
475     else
476     {
477         DesiredAccess = DuplicateHandleRequest->DesiredAccess;
478         /* Make sure the source handle has all the desired flags */
479         if ((Entry->Access & DesiredAccess) == 0)
480         {
481             DPRINT1("Handle 0x%p only has access %X; requested %X\n",
482                     SourceHandle, Entry->Access, DesiredAccess);
483             Status = STATUS_INVALID_PARAMETER;
484             goto Quit;
485         }
486     }
487 
488     /* Insert the new handle inside the process handles table */
489     Status = ConSrvInsertObject(ProcessData,
490                                 &DuplicateHandleRequest->TargetHandle,
491                                 Entry->Object,
492                                 DesiredAccess,
493                                 DuplicateHandleRequest->InheritHandle,
494                                 Entry->ShareMode);
495     if (NT_SUCCESS(Status) &&
496         (DuplicateHandleRequest->Options & DUPLICATE_CLOSE_SOURCE))
497     {
498         /* Close the original handle if needed */
499         ConSrvCloseHandle(Entry);
500     }
501 
502 Quit:
503     RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
504 
505     return Status;
506 }
507 
508 /* API_NUMBER: ConsolepGetHandleInformation */
CON_API(SrvGetHandleInformation,CONSOLE_GETHANDLEINFO,GetHandleInfoRequest)509 CON_API(SrvGetHandleInformation,
510         CONSOLE_GETHANDLEINFO, GetHandleInfoRequest)
511 {
512     NTSTATUS Status;
513     HANDLE Handle = GetHandleInfoRequest->Handle;
514     ULONG Index = HandleToULong(Handle) >> 2;
515     PCONSOLE_IO_HANDLE Entry;
516 
517     RtlEnterCriticalSection(&ProcessData->HandleTableLock);
518 
519     ASSERT(ProcessData->HandleTable);
520     // ASSERT( (ProcessData->HandleTable == NULL && ProcessData->HandleTableSize == 0) ||
521     //         (ProcessData->HandleTable != NULL && ProcessData->HandleTableSize != 0) );
522 
523     if (!IsConsoleHandle(Handle)              ||
524         Index >= ProcessData->HandleTableSize ||
525         (Entry = &ProcessData->HandleTable[Index])->Object == NULL)
526     {
527         Status = STATUS_INVALID_HANDLE;
528         goto Quit;
529     }
530 
531     /*
532      * Retrieve the handle information flags. The console server
533      * doesn't support HANDLE_FLAG_PROTECT_FROM_CLOSE.
534      */
535     GetHandleInfoRequest->Flags = 0;
536     if (Entry->Inheritable) GetHandleInfoRequest->Flags |= HANDLE_FLAG_INHERIT;
537 
538     Status = STATUS_SUCCESS;
539 
540 Quit:
541     RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
542 
543     return Status;
544 }
545 
546 /* API_NUMBER: ConsolepSetHandleInformation */
CON_API(SrvSetHandleInformation,CONSOLE_SETHANDLEINFO,SetHandleInfoRequest)547 CON_API(SrvSetHandleInformation,
548         CONSOLE_SETHANDLEINFO, SetHandleInfoRequest)
549 {
550     NTSTATUS Status;
551     HANDLE Handle = SetHandleInfoRequest->Handle;
552     ULONG Index = HandleToULong(Handle) >> 2;
553     PCONSOLE_IO_HANDLE Entry;
554 
555     RtlEnterCriticalSection(&ProcessData->HandleTableLock);
556 
557     ASSERT(ProcessData->HandleTable);
558     // ASSERT( (ProcessData->HandleTable == NULL && ProcessData->HandleTableSize == 0) ||
559     //         (ProcessData->HandleTable != NULL && ProcessData->HandleTableSize != 0) );
560 
561     if (!IsConsoleHandle(Handle)              ||
562         Index >= ProcessData->HandleTableSize ||
563         (Entry = &ProcessData->HandleTable[Index])->Object == NULL)
564     {
565         Status = STATUS_INVALID_HANDLE;
566         goto Quit;
567     }
568 
569     /*
570      * Modify the handle information flags. The console server
571      * doesn't support HANDLE_FLAG_PROTECT_FROM_CLOSE.
572      */
573     if (SetHandleInfoRequest->Mask & HANDLE_FLAG_INHERIT)
574     {
575         Entry->Inheritable = ((SetHandleInfoRequest->Flags & HANDLE_FLAG_INHERIT) != 0);
576     }
577 
578     Status = STATUS_SUCCESS;
579 
580 Quit:
581     RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
582 
583     return Status;
584 }
585 
586 /* API_NUMBER: ConsolepCloseHandle */
CON_API(SrvCloseHandle,CONSOLE_CLOSEHANDLE,CloseHandleRequest)587 CON_API(SrvCloseHandle,
588         CONSOLE_CLOSEHANDLE, CloseHandleRequest)
589 {
590     return ConSrvRemoveObject(ProcessData, CloseHandleRequest->Handle);
591 }
592 
593 /* API_NUMBER: ConsolepVerifyIoHandle */
CON_API(SrvVerifyConsoleIoHandle,CONSOLE_VERIFYHANDLE,VerifyHandleRequest)594 CON_API(SrvVerifyConsoleIoHandle,
595         CONSOLE_VERIFYHANDLE, VerifyHandleRequest)
596 {
597     HANDLE IoHandle = VerifyHandleRequest->Handle;
598     ULONG Index = HandleToULong(IoHandle) >> 2;
599 
600     VerifyHandleRequest->IsValid = FALSE;
601 
602     RtlEnterCriticalSection(&ProcessData->HandleTableLock);
603 
604     // ASSERT( (ProcessData->HandleTable == NULL && ProcessData->HandleTableSize == 0) ||
605     //         (ProcessData->HandleTable != NULL && ProcessData->HandleTableSize != 0) );
606 
607     if (!IsConsoleHandle(IoHandle)            ||
608         Index >= ProcessData->HandleTableSize ||
609         ProcessData->HandleTable[Index].Object == NULL)
610     {
611         DPRINT("SrvVerifyConsoleIoHandle failed\n");
612     }
613     else
614     {
615         VerifyHandleRequest->IsValid = TRUE;
616     }
617 
618     RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
619 
620     return STATUS_SUCCESS;
621 }
622 
623 /* EOF */
624