[KERNEL32]
[reactos.git] / win32ss / user / consrv / handle.c
1 /*
2 * LICENSE: GPL - See COPYING in the top level directory
3 * PROJECT: ReactOS Console Server DLL
4 * FILE: win32ss/user/consrv/handle.c
5 * PURPOSE: Console IO Handle functions
6 * PROGRAMMERS:
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include "consrv.h"
12 #include "conio.h"
13
14 #define NDEBUG
15 #include <debug.h>
16
17
18 /* PRIVATE FUNCTIONS *********************************************************/
19
20 static INT
21 AdjustHandleCounts(PCSRSS_HANDLE Entry, INT Change)
22 {
23 Object_t *Object = Entry->Object;
24
25 DPRINT1("AdjustHandleCounts(0x%p, %d), Object = 0x%p, Object->HandleCount = %d, Object->Type = %lu\n", Entry, Change, Object, Object->HandleCount, Object->Type);
26
27 if (Entry->Access & GENERIC_READ) Object->AccessRead += Change;
28 if (Entry->Access & GENERIC_WRITE) Object->AccessWrite += Change;
29 if (!(Entry->ShareMode & FILE_SHARE_READ)) Object->ExclusiveRead += Change;
30 if (!(Entry->ShareMode & FILE_SHARE_WRITE)) Object->ExclusiveWrite += Change;
31
32 Object->HandleCount += Change;
33
34 return Object->HandleCount;
35 }
36
37 static VOID
38 Win32CsrCreateHandleEntry(PCSRSS_HANDLE Entry)
39 {
40 Object_t *Object = Entry->Object;
41 EnterCriticalSection(&Object->Console->Lock);
42 AdjustHandleCounts(Entry, +1);
43 LeaveCriticalSection(&Object->Console->Lock);
44 }
45
46 static VOID
47 Win32CsrCloseHandleEntry(PCSRSS_HANDLE Entry)
48 {
49 Object_t *Object = Entry->Object;
50
51 if (Object != NULL)
52 {
53 PCSRSS_CONSOLE Console = Object->Console;
54 EnterCriticalSection(&Console->Lock);
55
56 if (Object->Type == CONIO_CONSOLE_MAGIC)
57 {
58 // LIST_ENTRY WaitQueue;
59
60 /*
61 * Wake-up all of the writing waiters if any, dereference them
62 * and purge them all from the list.
63 */
64 CsrNotifyWait(&Console->ReadWaitQueue,
65 WaitAll,
66 NULL,
67 (PVOID)0xdeaddead);
68 // InitializeListHead(&WaitQueue);
69
70 // CsrMoveSatisfiedWait(&WaitQueue, &Console->ReadWaitQueue);
71 if (!IsListEmpty(&Console->ReadWaitQueue /* &WaitQueue */))
72 {
73 CsrDereferenceWait(&Console->ReadWaitQueue /* &WaitQueue */);
74 }
75 }
76
77 /* If the last handle to a screen buffer is closed, delete it... */
78 if (AdjustHandleCounts(Entry, -1) == 0)
79 {
80 if (Object->Type == CONIO_SCREEN_BUFFER_MAGIC)
81 {
82 PCSRSS_SCREEN_BUFFER Buffer = (PCSRSS_SCREEN_BUFFER)Object;
83 /* ...unless it's the only buffer left. Windows allows deletion
84 * even of the last buffer, but having to deal with a lack of
85 * any active buffer might be error-prone. */
86 if (Buffer->ListEntry.Flink != Buffer->ListEntry.Blink)
87 ConioDeleteScreenBuffer(Buffer);
88 }
89 else if (Object->Type == CONIO_CONSOLE_MAGIC)
90 {
91 /* TODO: FIXME: Destroy here the console ?? */
92 // ConioDeleteConsole(Console);
93 }
94 }
95
96 LeaveCriticalSection(&Console->Lock);
97 Entry->Object = NULL;
98 }
99 }
100
101
102 /* FUNCTIONS *****************************************************************/
103
104 NTSTATUS
105 FASTCALL
106 Win32CsrInsertObject(PCONSOLE_PROCESS_DATA ProcessData,
107 PHANDLE Handle,
108 Object_t *Object,
109 DWORD Access,
110 BOOL Inheritable,
111 DWORD ShareMode)
112 {
113 ULONG i;
114 PCSRSS_HANDLE Block;
115
116 RtlEnterCriticalSection(&ProcessData->HandleTableLock);
117
118 for (i = 0; i < ProcessData->HandleTableSize; i++)
119 {
120 if (ProcessData->HandleTable[i].Object == NULL)
121 {
122 break;
123 }
124 }
125 if (i >= ProcessData->HandleTableSize)
126 {
127 Block = RtlAllocateHeap(ConSrvHeap,
128 HEAP_ZERO_MEMORY,
129 (ProcessData->HandleTableSize + 64) * sizeof(CSRSS_HANDLE));
130 if (Block == NULL)
131 {
132 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
133 return STATUS_UNSUCCESSFUL;
134 }
135 RtlCopyMemory(Block,
136 ProcessData->HandleTable,
137 ProcessData->HandleTableSize * sizeof(CSRSS_HANDLE));
138 RtlFreeHeap(ConSrvHeap, 0, ProcessData->HandleTable);
139 ProcessData->HandleTable = Block;
140 ProcessData->HandleTableSize += 64;
141 }
142 ProcessData->HandleTable[i].Object = Object;
143 ProcessData->HandleTable[i].Access = Access;
144 ProcessData->HandleTable[i].Inheritable = Inheritable;
145 ProcessData->HandleTable[i].ShareMode = ShareMode;
146 Win32CsrCreateHandleEntry(&ProcessData->HandleTable[i]);
147 *Handle = UlongToHandle((i << 2) | 0x3);
148 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
149 return STATUS_SUCCESS;
150 }
151
152 NTSTATUS
153 FASTCALL
154 Win32CsrReleaseObject(PCONSOLE_PROCESS_DATA ProcessData,
155 HANDLE Handle)
156 {
157 ULONG_PTR h = (ULONG_PTR)Handle >> 2;
158 Object_t *Object;
159
160 RtlEnterCriticalSection(&ProcessData->HandleTableLock);
161
162 if (h >= ProcessData->HandleTableSize ||
163 (Object = ProcessData->HandleTable[h].Object) == NULL)
164 {
165 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
166 return STATUS_INVALID_HANDLE;
167 }
168 Win32CsrCloseHandleEntry(&ProcessData->HandleTable[h]);
169
170 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
171
172 return STATUS_SUCCESS;
173 }
174
175 NTSTATUS
176 FASTCALL
177 Win32CsrLockObject(PCONSOLE_PROCESS_DATA ProcessData,
178 HANDLE Handle,
179 Object_t **Object,
180 DWORD Access,
181 LONG Type)
182 {
183 ULONG_PTR h = (ULONG_PTR)Handle >> 2;
184
185 DPRINT("Win32CsrLockObject, Object: %x, %x, %x\n",
186 Object, Handle, ProcessData ? ProcessData->HandleTableSize : 0);
187
188 RtlEnterCriticalSection(&ProcessData->HandleTableLock);
189
190 if ( !IsConsoleHandle(Handle) ||
191 h >= ProcessData->HandleTableSize ||
192 (*Object = ProcessData->HandleTable[h].Object) == NULL ||
193 ~ProcessData->HandleTable[h].Access & Access ||
194 (Type != 0 && (*Object)->Type != Type) )
195 {
196 DPRINT1("CsrGetObject returning invalid handle (%x)\n", Handle);
197 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
198 return STATUS_INVALID_HANDLE;
199 }
200
201 _InterlockedIncrement(&(*Object)->Console->ReferenceCount);
202 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
203
204 EnterCriticalSection(&((*Object)->Console->Lock));
205 return STATUS_SUCCESS;
206 }
207
208 VOID FASTCALL
209 Win32CsrUnlockConsole(PCSRSS_CONSOLE Console)
210 {
211 LeaveCriticalSection(&Console->Lock);
212
213 #if 0
214 /* If it was the last held lock for the owning thread... */
215 if (&Console->Lock.RecursionCount == 0)
216 {
217 /* ...dereference waiting threads if any */
218 LIST_ENTRY WaitQueue;
219 InitializeListHead(&WaitQueue);
220
221 CsrMoveSatisfiedWait(&WaitQueue, Console->SatisfiedWaits);
222 Console->SatisfiedWaits = NULL;
223 if (!IsListEmpty(&WaitQueue))
224 {
225 CsrDereferenceWait(&WaitQueue);
226 }
227 }
228 #endif
229
230 /* Decrement reference count */
231 if (_InterlockedDecrement(&Console->ReferenceCount) == 0)
232 ConioDeleteConsole(Console);
233 }
234
235 VOID
236 FASTCALL
237 Win32CsrUnlockObject(Object_t *Object)
238 {
239 Win32CsrUnlockConsole(Object->Console);
240 }
241
242
243
244 /** Remark: this function can be called by SrvAttachConsole (not yet implemented) **/
245 NTSTATUS
246 NTAPI
247 ConsoleNewProcess(PCSR_PROCESS SourceProcess,
248 PCSR_PROCESS TargetProcess)
249 {
250 /**************************************************************************
251 * This function is called whenever a new process (GUI or CUI) is created.
252 *
253 * Copy the parent's handles table here if both the parent and the child
254 * processes are CUI. If we must actually create our proper console (and
255 * thus do not inherit from the console handles of the parent's), then we
256 * will clean this table in the next ConsoleConnect call. Why we are doing
257 * this? It's because here, we still don't know whether or not we must create
258 * a new console instead of inherit it from the parent, and, because in
259 * ConsoleConnect we don't have any reference to the parent process anymore.
260 **************************************************************************/
261
262 PCONSOLE_PROCESS_DATA SourceProcessData, TargetProcessData;
263 ULONG i;
264
265 DPRINT1("ConsoleNewProcess inside\n");
266 DPRINT1("SourceProcess = 0x%p ; TargetProcess = 0x%p\n", SourceProcess, TargetProcess);
267
268 /* An empty target process is invalid */
269 if (!TargetProcess)
270 return STATUS_INVALID_PARAMETER;
271
272 DPRINT1("ConsoleNewProcess - OK\n");
273
274 TargetProcessData = ConsoleGetPerProcessData(TargetProcess);
275 DPRINT1("TargetProcessData = 0x%p\n", TargetProcessData);
276
277 /**** HACK !!!! ****/ RtlZeroMemory(TargetProcessData, sizeof(*TargetProcessData));
278
279 /* Initialize the new (target) process */
280 TargetProcessData->Process = TargetProcess;
281 TargetProcessData->ConsoleEvent = NULL;
282 TargetProcessData->Console = TargetProcessData->ParentConsole = NULL;
283 // TargetProcessData->bInheritHandles = FALSE;
284 TargetProcessData->ConsoleApp = ((TargetProcess->Flags & CsrProcessIsConsoleApp) ? TRUE : FALSE);
285
286 // Testing
287 TargetProcessData->HandleTableSize = 0;
288 TargetProcessData->HandleTable = NULL;
289
290 /* HACK */ RtlZeroMemory(&TargetProcessData->HandleTableLock, sizeof(RTL_CRITICAL_SECTION));
291 RtlInitializeCriticalSection(&TargetProcessData->HandleTableLock);
292
293 /* Do nothing if the source process is NULL */
294 if (!SourceProcess)
295 return STATUS_SUCCESS;
296
297 SourceProcessData = ConsoleGetPerProcessData(SourceProcess);
298 DPRINT1("SourceProcessData = 0x%p\n", SourceProcessData);
299
300 /*
301 * If both of the processes (parent and new child) are console applications,
302 * then try to inherit handles from the parent process.
303 */
304 if ( SourceProcessData->Console != NULL && /* SourceProcessData->ConsoleApp */
305 TargetProcessData->ConsoleApp )
306 {
307 /*
308 if (TargetProcessData->HandleTableSize)
309 {
310 return STATUS_INVALID_PARAMETER;
311 }
312 */
313
314 DPRINT1("ConsoleNewProcess - Copy the handle table (1)\n");
315 /* Temporary "inherit" the console from the parent */
316 TargetProcessData->ParentConsole = SourceProcessData->Console;
317 RtlEnterCriticalSection(&SourceProcessData->HandleTableLock);
318 DPRINT1("ConsoleNewProcess - Copy the handle table (2)\n");
319
320 /* Allocate a new handle table for the child process */
321 TargetProcessData->HandleTable = RtlAllocateHeap(ConSrvHeap,
322 HEAP_ZERO_MEMORY,
323 SourceProcessData->HandleTableSize
324 * sizeof(CSRSS_HANDLE));
325 if (TargetProcessData->HandleTable == NULL)
326 {
327 RtlLeaveCriticalSection(&SourceProcessData->HandleTableLock);
328 return STATUS_UNSUCCESSFUL;
329 }
330
331 TargetProcessData->HandleTableSize = SourceProcessData->HandleTableSize;
332
333 /*
334 * Parse the parent process' handles table and, for each handle,
335 * do a copy of it and reference it, if the handle is inheritable.
336 */
337 for (i = 0; i < SourceProcessData->HandleTableSize; i++)
338 {
339 if (SourceProcessData->HandleTable[i].Object != NULL &&
340 SourceProcessData->HandleTable[i].Inheritable)
341 {
342 /*
343 * Copy the handle data and increment the reference count of the
344 * pointed object (via the call to Win32CsrCreateHandleEntry).
345 */
346 TargetProcessData->HandleTable[i] = SourceProcessData->HandleTable[i];
347 Win32CsrCreateHandleEntry(&TargetProcessData->HandleTable[i]);
348 }
349 }
350
351 RtlLeaveCriticalSection(&SourceProcessData->HandleTableLock);
352 }
353 else
354 {
355 DPRINT1("ConsoleNewProcess - We don't launch a Console process : SourceProcessData->Console = 0x%p ; TargetProcess->Flags = %lu\n", SourceProcessData->Console, TargetProcess->Flags);
356 }
357
358 return STATUS_SUCCESS;
359 }
360
361 // Temporary ; move it to a header.
362 NTSTATUS WINAPI CsrInitConsole(PCSRSS_CONSOLE* NewConsole, int ShowCmd);
363
364 NTSTATUS
365 NTAPI
366 ConsoleConnect(IN PCSR_PROCESS CsrProcess,
367 IN OUT PVOID ConnectionInfo,
368 IN OUT PULONG ConnectionInfoLength)
369 {
370 /**************************************************************************
371 * This function is called whenever a CUI new process is created.
372 **************************************************************************/
373
374 NTSTATUS Status = STATUS_SUCCESS;
375 PCONSOLE_CONNECTION_INFO ConnectInfo = (PCONSOLE_CONNECTION_INFO)ConnectionInfo;
376 PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrProcess);
377 BOOLEAN NewConsole = FALSE;
378 // PCSRSS_CONSOLE Console = NULL;
379
380 DPRINT1("ConsoleConnect\n");
381
382 if ( ConnectionInfo == NULL ||
383 ConnectionInfoLength == NULL ||
384 *ConnectionInfoLength != sizeof(CONSOLE_CONNECTION_INFO) )
385 {
386 DPRINT1("CONSRV: Connection failed\n");
387 return STATUS_UNSUCCESSFUL;
388 }
389
390 /* If we don't need a console, then get out of here */
391 if (!ConnectInfo->ConsoleNeeded || !ProcessData->ConsoleApp) // In fact, it is for GUI apps.
392 {
393 DPRINT("ConsoleConnect - No console needed\n");
394 return STATUS_SUCCESS;
395 }
396
397 RtlEnterCriticalSection(&ProcessData->HandleTableLock);
398
399 /* If we don't have a console, then create a new one... */
400 if (!ConnectInfo->Console ||
401 ConnectInfo->Console != ProcessData->ParentConsole)
402 {
403 // PCSRSS_CONSOLE Console;
404
405 DPRINT1("ConsoleConnect - Allocate a new console\n");
406
407 /* Initialize a new Console */
408 NewConsole = TRUE;
409 Status = CsrInitConsole(&ProcessData->Console, ConnectInfo->ShowCmd);
410 if (!NT_SUCCESS(Status))
411 {
412 DPRINT1("Console initialization failed\n");
413 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
414 return Status;
415 }
416 }
417 else /* We inherit it from the parent */
418 {
419 DPRINT1("ConsoleConnect - Reuse current (parent's) console\n");
420
421 /* Reuse our current console */
422 NewConsole = FALSE;
423 ProcessData->Console = ConnectInfo->Console;
424 }
425
426 /* Insert the process into the processes list of the console */
427 InsertHeadList(&ProcessData->Console->ProcessList, &ProcessData->ConsoleLink);
428
429 /* Return it to the caller */
430 ConnectInfo->Console = ProcessData->Console;
431
432 /* Add a reference count because the process is tied to the console */
433 _InterlockedIncrement(&ProcessData->Console->ReferenceCount);
434
435 if (NewConsole /* || !ProcessData->bInheritHandles */)
436 {
437 /*
438 * We've just created a new console. However when ConsoleNewProcess was
439 * called, we didn't know that we wanted to create a new console and
440 * therefore, we by default inherited the handles table from our parent
441 * process. It's only now that we notice that in fact we do not need
442 * them, because we've created a new console and thus we must use it.
443 *
444 * Therefore, free our handles table and recreate a new one.
445 */
446
447 ULONG i;
448
449 /* Close all console handles and free the handle table memory */
450 for (i = 0; i < ProcessData->HandleTableSize; i++)
451 {
452 Win32CsrCloseHandleEntry(&ProcessData->HandleTable[i]);
453 }
454 ProcessData->HandleTableSize = 0;
455 RtlFreeHeap(ConSrvHeap, 0, ProcessData->HandleTable);
456 ProcessData->HandleTable = NULL;
457
458 /*
459 * Create a new handle table - Insert the IO handles
460 */
461
462 /* Insert the Input handle */
463 Status = Win32CsrInsertObject(ProcessData,
464 &ConnectInfo->InputHandle,
465 &ProcessData->Console->Header,
466 GENERIC_READ | GENERIC_WRITE,
467 TRUE,
468 FILE_SHARE_READ | FILE_SHARE_WRITE);
469 if (!NT_SUCCESS(Status))
470 {
471 DPRINT1("Failed to insert the input handle\n");
472 ConioDeleteConsole(ProcessData->Console);
473 ProcessData->Console = NULL;
474 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
475 return Status;
476 }
477
478 /* Insert the Output handle */
479 Status = Win32CsrInsertObject(ProcessData,
480 &ConnectInfo->OutputHandle,
481 &ProcessData->Console->ActiveBuffer->Header,
482 GENERIC_READ | GENERIC_WRITE,
483 TRUE,
484 FILE_SHARE_READ | FILE_SHARE_WRITE);
485 if (!NT_SUCCESS(Status))
486 {
487 DPRINT1("Failed to insert the output handle\n");
488 ConioDeleteConsole(ProcessData->Console);
489 Win32CsrReleaseObject(ProcessData,
490 ConnectInfo->InputHandle);
491 ProcessData->Console = NULL;
492 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
493 return Status;
494 }
495
496 /* Insert the Error handle */
497 Status = Win32CsrInsertObject(ProcessData,
498 &ConnectInfo->ErrorHandle,
499 &ProcessData->Console->ActiveBuffer->Header,
500 GENERIC_READ | GENERIC_WRITE,
501 TRUE,
502 FILE_SHARE_READ | FILE_SHARE_WRITE);
503 if (!NT_SUCCESS(Status))
504 {
505 DPRINT1("Failed to insert the error handle\n");
506 ConioDeleteConsole(ProcessData->Console);
507 Win32CsrReleaseObject(ProcessData,
508 ConnectInfo->OutputHandle);
509 Win32CsrReleaseObject(ProcessData,
510 ConnectInfo->InputHandle);
511 ProcessData->Console = NULL;
512 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
513 return Status;
514 }
515 }
516
517 /* Duplicate the Event */
518 Status = NtDuplicateObject(NtCurrentProcess(),
519 ProcessData->Console->ActiveEvent,
520 ProcessData->Process->ProcessHandle,
521 &ProcessData->ConsoleEvent,
522 EVENT_ALL_ACCESS, 0, 0);
523 if (!NT_SUCCESS(Status))
524 {
525 DPRINT1("NtDuplicateObject() failed: %lu\n", Status);
526 ConioDeleteConsole(ProcessData->Console);
527 if (NewConsole /* || !ProcessData->bInheritHandles */)
528 {
529 Win32CsrReleaseObject(ProcessData,
530 ConnectInfo->ErrorHandle);
531 Win32CsrReleaseObject(ProcessData,
532 ConnectInfo->OutputHandle);
533 Win32CsrReleaseObject(ProcessData,
534 ConnectInfo->InputHandle);
535 }
536 ProcessData->Console = NULL;
537 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
538 return Status;
539 }
540 /* Input Wait Handle */
541 ConnectInfo->InputWaitHandle = ProcessData->ConsoleEvent;
542
543 /* Set the Ctrl Dispatcher */
544 ProcessData->CtrlDispatcher = ConnectInfo->CtrlDispatcher;
545 DPRINT("CSRSS:CtrlDispatcher address: %x\n", ProcessData->CtrlDispatcher);
546
547 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
548 return STATUS_SUCCESS;
549 }
550
551 VOID
552 WINAPI
553 Win32CsrReleaseConsole(PCSR_PROCESS Process)
554 {
555 PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(Process);
556 PCSRSS_CONSOLE Console;
557 ULONG i;
558
559 DPRINT1("Win32CsrReleaseConsole\n");
560
561 RtlEnterCriticalSection(&ProcessData->HandleTableLock);
562
563 /* Close all console handles and free the handle table memory */
564 for (i = 0; i < ProcessData->HandleTableSize; i++)
565 {
566 Win32CsrCloseHandleEntry(&ProcessData->HandleTable[i]);
567 }
568 ProcessData->HandleTableSize = 0;
569 RtlFreeHeap(ConSrvHeap, 0, ProcessData->HandleTable);
570 ProcessData->HandleTable = NULL;
571
572 /* Detach process from console */
573 Console = ProcessData->Console;
574 if (Console != NULL)
575 {
576 DPRINT1("Win32CsrReleaseConsole - Console->ReferenceCount = %lu - We are going to decrement it !\n", Console->ReferenceCount);
577 ProcessData->Console = NULL;
578 EnterCriticalSection(&Console->Lock);
579 RemoveEntryList(&ProcessData->ConsoleLink);
580 Win32CsrUnlockConsole(Console);
581 //CloseHandle(ProcessData->ConsoleEvent);
582 //ProcessData->ConsoleEvent = NULL;
583 }
584
585 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
586 }
587
588 VOID
589 WINAPI
590 ConsoleDisconnect(PCSR_PROCESS Process)
591 {
592 PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(Process);
593
594 /**************************************************************************
595 * This function is called whenever a new process (GUI or CUI) is destroyed.
596 *
597 * Only do something if the process is a CUI. <-- modify this behaviour if
598 * we deal with a GUI which
599 * quits and acquired a
600 * console...
601 **************************************************************************/
602
603 DPRINT1("ConsoleDisconnect called\n");
604 // if (ProcessData->Console != NULL)
605 if (ProcessData->ConsoleApp)
606 {
607 DPRINT1("ConsoleDisconnect - calling Win32CsrReleaseConsole\n");
608 Win32CsrReleaseConsole(Process);
609 }
610
611 RtlDeleteCriticalSection(&ProcessData->HandleTableLock);
612 }
613
614
615
616 CSR_API(SrvCloseHandle)
617 {
618 PCSRSS_CLOSE_HANDLE CloseHandleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.CloseHandleRequest;
619
620 return Win32CsrReleaseObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process),
621 CloseHandleRequest->Handle);
622 }
623
624 CSR_API(SrvVerifyConsoleIoHandle)
625 {
626 NTSTATUS Status = STATUS_SUCCESS;
627 PCSRSS_VERIFY_HANDLE VerifyHandleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.VerifyHandleRequest;
628 PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
629 HANDLE Handle = VerifyHandleRequest->Handle;
630 ULONG_PTR Index = (ULONG_PTR)Handle >> 2;
631
632 RtlEnterCriticalSection(&ProcessData->HandleTableLock);
633
634 if (!IsConsoleHandle(Handle) ||
635 Index >= ProcessData->HandleTableSize ||
636 ProcessData->HandleTable[Index].Object == NULL)
637 {
638 DPRINT("CsrVerifyObject failed\n");
639 Status = STATUS_INVALID_HANDLE;
640 }
641
642 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
643
644 return Status;
645 }
646
647 CSR_API(SrvDuplicateHandle)
648 {
649 PCSRSS_HANDLE Entry;
650 DWORD DesiredAccess;
651 PCSRSS_DUPLICATE_HANDLE DuplicateHandleRequest = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.DuplicateHandleRequest;
652 PCONSOLE_PROCESS_DATA ProcessData = ConsoleGetPerProcessData(CsrGetClientThread()->Process);
653 HANDLE Handle = DuplicateHandleRequest->Handle;
654 ULONG_PTR Index = (ULONG_PTR)Handle >> 2;
655
656 RtlEnterCriticalSection(&ProcessData->HandleTableLock);
657
658 if ( /** !IsConsoleHandle(Handle) || **/
659 Index >= ProcessData->HandleTableSize ||
660 (Entry = &ProcessData->HandleTable[Index])->Object == NULL)
661 {
662 DPRINT1("Couldn't duplicate invalid handle %p\n", Handle);
663 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
664 return STATUS_INVALID_HANDLE;
665 }
666
667 if (DuplicateHandleRequest->Options & DUPLICATE_SAME_ACCESS)
668 {
669 DesiredAccess = Entry->Access;
670 }
671 else
672 {
673 DesiredAccess = DuplicateHandleRequest->Access;
674 /* Make sure the source handle has all the desired flags */
675 if (~Entry->Access & DesiredAccess)
676 {
677 DPRINT1("Handle %p only has access %X; requested %X\n",
678 Handle, Entry->Access, DesiredAccess);
679 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
680 return STATUS_INVALID_PARAMETER;
681 }
682 }
683
684 ApiMessage->Status = Win32CsrInsertObject(ProcessData,
685 &DuplicateHandleRequest->Handle, // Use the new handle value!
686 Entry->Object,
687 DesiredAccess,
688 DuplicateHandleRequest->Inheritable,
689 Entry->ShareMode);
690 if (NT_SUCCESS(ApiMessage->Status) &&
691 DuplicateHandleRequest->Options & DUPLICATE_CLOSE_SOURCE)
692 {
693 Win32CsrCloseHandleEntry(Entry);
694 }
695
696 RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
697 return ApiMessage->Status;
698 }
699
700 /**
701 CSR_API(CsrGetInputWaitHandle)
702 {
703 PCSRSS_GET_INPUT_WAIT_HANDLE GetConsoleInputWaitHandle = &((PCONSOLE_API_MESSAGE)ApiMessage)->Data.GetConsoleInputWaitHandle;
704
705 GetConsoleInputWaitHandle->InputWaitHandle =
706 ConsoleGetPerProcessData(CsrGetClientThread()->Process)->ConsoleEvent;
707
708 return STATUS_SUCCESS;
709 }
710 **/
711
712 /* EOF */