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: Handle functions
9 /* INCLUDES ******************************************************************/
18 /* FUNCTIONS *****************************************************************/
22 CsrIsConsoleHandle(HANDLE Handle
)
24 return ((ULONG_PTR
)Handle
& 0x10000003) == 0x3;
28 AdjustHandleCounts(PCSRSS_HANDLE Entry
, INT Change
)
30 Object_t
*Object
= Entry
->Object
;
31 if (Entry
->Access
& GENERIC_READ
) Object
->AccessRead
+= Change
;
32 if (Entry
->Access
& GENERIC_WRITE
) Object
->AccessWrite
+= Change
;
33 if (!(Entry
->ShareMode
& FILE_SHARE_READ
)) Object
->ExclusiveRead
+= Change
;
34 if (!(Entry
->ShareMode
& FILE_SHARE_WRITE
)) Object
->ExclusiveWrite
+= Change
;
35 Object
->HandleCount
+= Change
;
36 return Object
->HandleCount
;
40 Win32CsrCreateHandleEntry(PCSRSS_HANDLE Entry
)
42 Object_t
*Object
= Entry
->Object
;
43 EnterCriticalSection(&Object
->Console
->Lock
);
44 AdjustHandleCounts(Entry
, +1);
45 LeaveCriticalSection(&Object
->Console
->Lock
);
49 Win32CsrCloseHandleEntry(PCSRSS_HANDLE Entry
)
51 Object_t
*Object
= Entry
->Object
;
54 PCSRSS_CONSOLE Console
= Object
->Console
;
55 EnterCriticalSection(&Console
->Lock
);
56 /* If the last handle to a screen buffer is closed, delete it */
57 if (AdjustHandleCounts(Entry
, -1) == 0
58 && Object
->Type
== CONIO_SCREEN_BUFFER_MAGIC
)
60 PCSRSS_SCREEN_BUFFER Buffer
= (PCSRSS_SCREEN_BUFFER
)Object
;
61 /* ...unless it's the only buffer left. Windows allows deletion
62 * even of the last buffer, but having to deal with a lack of
63 * any active buffer might be error-prone. */
64 if (Buffer
->ListEntry
.Flink
!= Buffer
->ListEntry
.Blink
)
65 ConioDeleteScreenBuffer(Buffer
);
67 LeaveCriticalSection(&Console
->Lock
);
74 Win32CsrReleaseObject(PCONSOLE_PROCESS_DATA ProcessData
,
77 ULONG_PTR h
= (ULONG_PTR
)Handle
>> 2;
80 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
81 if (h
>= ProcessData
->HandleTableSize
82 || (Object
= ProcessData
->HandleTable
[h
].Object
) == NULL
)
84 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
85 return STATUS_INVALID_HANDLE
;
87 Win32CsrCloseHandleEntry(&ProcessData
->HandleTable
[h
]);
88 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
89 return STATUS_SUCCESS
;
94 Win32CsrLockObject(PCONSOLE_PROCESS_DATA ProcessData
,
100 ULONG_PTR h
= (ULONG_PTR
)Handle
>> 2;
102 DPRINT("Win32CsrLockObject, Object: %x, %x, %x\n",
103 Object
, Handle
, ProcessData
? ProcessData
->HandleTableSize
: 0);
105 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
106 if (!CsrIsConsoleHandle(Handle
) || h
>= ProcessData
->HandleTableSize
107 || (*Object
= ProcessData
->HandleTable
[h
].Object
) == NULL
108 || ~ProcessData
->HandleTable
[h
].Access
& Access
109 || (Type
!= 0 && (*Object
)->Type
!= Type
))
111 DPRINT1("CsrGetObject returning invalid handle (%x)\n", Handle
);
112 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
113 return STATUS_INVALID_HANDLE
;
115 _InterlockedIncrement(&(*Object
)->Console
->ReferenceCount
);
116 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
118 EnterCriticalSection(&((*Object
)->Console
->Lock
));
119 return STATUS_SUCCESS
;
124 Win32CsrUnlockObject(Object_t
*Object
)
126 PCSRSS_CONSOLE Console
= Object
->Console
;
127 LeaveCriticalSection(&Console
->Lock
);
129 if (_InterlockedDecrement(&Console
->ReferenceCount
) == 0)
130 ConioDeleteConsole(&Console
->Header
);
135 ConsoleNewProcess(PCSR_PROCESS SourceProcess
,
136 PCSR_PROCESS TargetProcess
)
138 PCONSOLE_PROCESS_DATA SourceProcessData
, TargetProcessData
;
141 DPRINT1("ConsoleNewProcess inside\n");
142 DPRINT1("SourceProcess = 0x%p ; TargetProcess = 0x%p\n", SourceProcess
, TargetProcess
);
144 /* An empty target process is invalid */
146 return STATUS_INVALID_PARAMETER
;
148 DPRINT1("ConsoleNewProcess - OK\n");
150 TargetProcessData
= ConsoleGetPerProcessData(TargetProcess
);
152 /* Initialize the new (target) process */
153 TargetProcessData
->Process
= TargetProcess
;
154 RtlInitializeCriticalSection(&TargetProcessData
->HandleTableLock
);
156 /* Do nothing if the source process is NULL */
158 return STATUS_SUCCESS
;
160 SourceProcessData
= ConsoleGetPerProcessData(SourceProcess
);
162 // TODO: Check if one of the processes is really a CONSOLE.
164 if (!(CreateProcessRequest->CreationFlags & (CREATE_NEW_CONSOLE | DETACHED_PROCESS)))
166 // NewProcess == TargetProcess.
167 NewProcess->ParentConsole = Process->Console;
168 NewProcess->bInheritHandles = CreateProcessRequest->bInheritHandles;
172 /* Only inherit if the if the flag was set */
173 if (!TargetProcessData
->bInheritHandles
) return STATUS_SUCCESS
;
175 if (TargetProcessData
->HandleTableSize
)
177 return STATUS_INVALID_PARAMETER
;
180 RtlEnterCriticalSection(&SourceProcessData
->HandleTableLock
);
182 TargetProcessData
->HandleTable
= RtlAllocateHeap(ConSrvHeap
,
184 SourceProcessData
->HandleTableSize
185 * sizeof(CSRSS_HANDLE
));
186 if (TargetProcessData
->HandleTable
== NULL
)
188 RtlLeaveCriticalSection(&SourceProcessData
->HandleTableLock
);
189 return STATUS_UNSUCCESSFUL
;
192 TargetProcessData
->HandleTableSize
= SourceProcessData
->HandleTableSize
;
194 for (i
= 0; i
< SourceProcessData
->HandleTableSize
; i
++)
196 if (SourceProcessData
->HandleTable
[i
].Object
!= NULL
&&
197 SourceProcessData
->HandleTable
[i
].Inheritable
)
199 TargetProcessData
->HandleTable
[i
] = SourceProcessData
->HandleTable
[i
];
200 Win32CsrCreateHandleEntry(&TargetProcessData
->HandleTable
[i
]);
204 RtlLeaveCriticalSection(&SourceProcessData
->HandleTableLock
);
206 return STATUS_SUCCESS
;
211 Win32CsrReleaseConsole(PCSR_PROCESS Process
)
213 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(Process
);
214 PCSRSS_CONSOLE Console
;
217 /* Close all console handles and detach process from console */
218 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
220 for (i
= 0; i
< ProcessData
->HandleTableSize
; i
++)
221 Win32CsrCloseHandleEntry(&ProcessData
->HandleTable
[i
]);
222 ProcessData
->HandleTableSize
= 0;
223 RtlFreeHeap(ConSrvHeap
, 0, ProcessData
->HandleTable
);
224 ProcessData
->HandleTable
= NULL
;
226 Console
= ProcessData
->Console
;
229 ProcessData
->Console
= NULL
;
230 EnterCriticalSection(&Console
->Lock
);
231 RemoveEntryList(&ProcessData
->ConsoleLink
);
232 LeaveCriticalSection(&Console
->Lock
);
233 if (_InterlockedDecrement(&Console
->ReferenceCount
) == 0)
234 ConioDeleteConsole(&Console
->Header
);
235 //CloseHandle(ProcessData->ConsoleEvent);
236 //ProcessData->ConsoleEvent = NULL;
238 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
243 Win32CsrInsertObject(PCONSOLE_PROCESS_DATA ProcessData
,
253 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
255 for (i
= 0; i
< ProcessData
->HandleTableSize
; i
++)
257 if (ProcessData
->HandleTable
[i
].Object
== NULL
)
262 if (i
>= ProcessData
->HandleTableSize
)
264 Block
= RtlAllocateHeap(ConSrvHeap
,
266 (ProcessData
->HandleTableSize
+ 64) * sizeof(CSRSS_HANDLE
));
269 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
270 return(STATUS_UNSUCCESSFUL
);
273 ProcessData
->HandleTable
,
274 ProcessData
->HandleTableSize
* sizeof(CSRSS_HANDLE
));
275 RtlFreeHeap(ConSrvHeap
, 0, ProcessData
->HandleTable
);
276 ProcessData
->HandleTable
= Block
;
277 ProcessData
->HandleTableSize
+= 64;
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 Win32CsrCreateHandleEntry(&ProcessData
->HandleTable
[i
]);
284 *Handle
= UlongToHandle((i
<< 2) | 0x3);
285 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
286 return STATUS_SUCCESS
;
289 CSR_API(SrvCloseHandle
)
291 PCSRSS_CLOSE_HANDLE CloseHandleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.CloseHandleRequest
;
293 return Win32CsrReleaseObject(ConsoleGetPerProcessData(CsrGetClientThread()->Process
),
294 CloseHandleRequest
->Handle
);
297 CSR_API(SrvVerifyConsoleIoHandle
)
299 NTSTATUS Status
= STATUS_SUCCESS
;
300 PCSRSS_VERIFY_HANDLE VerifyHandleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.VerifyHandleRequest
;
301 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
304 Index
= (ULONG_PTR
)VerifyHandleRequest
->Handle
>> 2;
305 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
306 if (Index
>= ProcessData
->HandleTableSize
||
307 ProcessData
->HandleTable
[Index
].Object
== NULL
)
309 DPRINT("CsrVerifyObject failed\n");
310 Status
= STATUS_INVALID_HANDLE
;
312 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
317 CSR_API(SrvDuplicateHandle
)
322 PCSRSS_DUPLICATE_HANDLE DuplicateHandleRequest
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.DuplicateHandleRequest
;
323 PCONSOLE_PROCESS_DATA ProcessData
= ConsoleGetPerProcessData(CsrGetClientThread()->Process
);
325 Index
= (ULONG_PTR
)DuplicateHandleRequest
->Handle
>> 2;
326 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
327 if (Index
>= ProcessData
->HandleTableSize
328 || (Entry
= &ProcessData
->HandleTable
[Index
])->Object
== NULL
)
330 DPRINT1("Couldn't dup invalid handle %p\n", DuplicateHandleRequest
->Handle
);
331 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
332 return STATUS_INVALID_HANDLE
;
335 if (DuplicateHandleRequest
->Options
& DUPLICATE_SAME_ACCESS
)
337 DesiredAccess
= Entry
->Access
;
341 DesiredAccess
= DuplicateHandleRequest
->Access
;
342 /* Make sure the source handle has all the desired flags */
343 if (~Entry
->Access
& DesiredAccess
)
345 DPRINT1("Handle %p only has access %X; requested %X\n",
346 DuplicateHandleRequest
->Handle
, Entry
->Access
, DesiredAccess
);
347 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
348 return STATUS_INVALID_PARAMETER
;
352 ApiMessage
->Status
= Win32CsrInsertObject(ProcessData
,
353 &DuplicateHandleRequest
->Handle
,
356 DuplicateHandleRequest
->Inheritable
,
358 if (NT_SUCCESS(ApiMessage
->Status
)
359 && DuplicateHandleRequest
->Options
& DUPLICATE_CLOSE_SOURCE
)
361 Win32CsrCloseHandleEntry(Entry
);
364 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
365 return ApiMessage
->Status
;
368 CSR_API(CsrGetInputWaitHandle
)
370 PCSRSS_GET_INPUT_WAIT_HANDLE GetConsoleInputWaitHandle
= &((PCONSOLE_API_MESSAGE
)ApiMessage
)->Data
.GetConsoleInputWaitHandle
;
372 GetConsoleInputWaitHandle
->InputWaitHandle
=
373 ConsoleGetPerProcessData(CsrGetClientThread()->Process
)->ConsoleEvent
;
375 return STATUS_SUCCESS
;