3 * reactos/subsys/csrss/api/handle.c
5 * CSRSS handle functions
7 * ReactOS Operating System
10 /* INCLUDES ******************************************************************/
17 /* FUNCTIONS *****************************************************************/
21 CsrIsConsoleHandle(HANDLE Handle
)
23 return ((ULONG_PTR
)Handle
& 0x10000003) == 0x3;
27 AdjustHandleCounts(PCSRSS_HANDLE Entry
, INT Change
)
29 Object_t
*Object
= Entry
->Object
;
30 if (Entry
->Access
& GENERIC_READ
) Object
->AccessRead
+= Change
;
31 if (Entry
->Access
& GENERIC_WRITE
) Object
->AccessWrite
+= Change
;
32 if (!(Entry
->ShareMode
& FILE_SHARE_READ
)) Object
->ExclusiveRead
+= Change
;
33 if (!(Entry
->ShareMode
& FILE_SHARE_WRITE
)) Object
->ExclusiveWrite
+= Change
;
34 Object
->HandleCount
+= Change
;
35 return Object
->HandleCount
;
39 Win32CsrCreateHandleEntry(
42 Object_t
*Object
= Entry
->Object
;
43 EnterCriticalSection(&Object
->Console
->Lock
);
44 AdjustHandleCounts(Entry
, +1);
45 LeaveCriticalSection(&Object
->Console
->Lock
);
49 Win32CsrCloseHandleEntry(
52 Object_t
*Object
= Entry
->Object
;
55 PCSRSS_CONSOLE Console
= Object
->Console
;
56 EnterCriticalSection(&Console
->Lock
);
57 /* If the last handle to a screen buffer is closed, delete it */
58 if (AdjustHandleCounts(Entry
, -1) == 0
59 && Object
->Type
== CONIO_SCREEN_BUFFER_MAGIC
)
61 PCSRSS_SCREEN_BUFFER Buffer
= (PCSRSS_SCREEN_BUFFER
)Object
;
62 /* ...unless it's the only buffer left. Windows allows deletion
63 * even of the last buffer, but having to deal with a lack of
64 * any active buffer might be error-prone. */
65 if (Buffer
->ListEntry
.Flink
!= Buffer
->ListEntry
.Blink
)
66 ConioDeleteScreenBuffer(Buffer
);
68 LeaveCriticalSection(&Console
->Lock
);
75 Win32CsrReleaseObject(
76 PCSRSS_PROCESS_DATA ProcessData
,
79 ULONG_PTR h
= (ULONG_PTR
)Handle
>> 2;
82 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
83 if (h
>= ProcessData
->HandleTableSize
84 || (Object
= ProcessData
->HandleTable
[h
].Object
) == NULL
)
86 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
87 return STATUS_INVALID_HANDLE
;
89 Win32CsrCloseHandleEntry(&ProcessData
->HandleTable
[h
]);
90 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
91 return STATUS_SUCCESS
;
96 Win32CsrLockObject(PCSRSS_PROCESS_DATA ProcessData
,
102 ULONG_PTR h
= (ULONG_PTR
)Handle
>> 2;
104 DPRINT("CsrGetObject, Object: %x, %x, %x\n",
105 Object
, Handle
, ProcessData
? ProcessData
->HandleTableSize
: 0);
107 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
108 if (!CsrIsConsoleHandle(Handle
) || h
>= ProcessData
->HandleTableSize
109 || (*Object
= ProcessData
->HandleTable
[h
].Object
) == NULL
110 || ~ProcessData
->HandleTable
[h
].Access
& Access
111 || (Type
!= 0 && (*Object
)->Type
!= Type
))
113 DPRINT1("CsrGetObject returning invalid handle (%x)\n", Handle
);
114 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
115 return STATUS_INVALID_HANDLE
;
117 _InterlockedIncrement(&(*Object
)->Console
->ReferenceCount
);
118 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
120 EnterCriticalSection(&((*Object
)->Console
->Lock
));
121 return STATUS_SUCCESS
;
126 Win32CsrUnlockObject(Object_t
*Object
)
128 PCSRSS_CONSOLE Console
= Object
->Console
;
129 LeaveCriticalSection(&Console
->Lock
);
131 if (_InterlockedDecrement(&Console
->ReferenceCount
) == 0)
132 ConioDeleteConsole(&Console
->Header
);
137 Win32CsrReleaseConsole(
138 PCSRSS_PROCESS_DATA ProcessData
)
140 PCSRSS_CONSOLE Console
;
143 /* Close all console handles and detach process from console */
144 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
146 for (i
= 0; i
< ProcessData
->HandleTableSize
; i
++)
147 Win32CsrCloseHandleEntry(&ProcessData
->HandleTable
[i
]);
148 ProcessData
->HandleTableSize
= 0;
149 RtlFreeHeap(Win32CsrApiHeap
, 0, ProcessData
->HandleTable
);
150 ProcessData
->HandleTable
= NULL
;
152 Console
= ProcessData
->Console
;
155 ProcessData
->Console
= NULL
;
156 EnterCriticalSection(&Console
->Lock
);
157 RemoveEntryList(&ProcessData
->ProcessEntry
);
158 LeaveCriticalSection(&Console
->Lock
);
159 if (_InterlockedDecrement(&Console
->ReferenceCount
) == 0)
160 ConioDeleteConsole(&Console
->Header
);
161 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
162 return STATUS_SUCCESS
;
164 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
165 return STATUS_INVALID_PARAMETER
;
170 Win32CsrInsertObject(
171 PCSRSS_PROCESS_DATA ProcessData
,
181 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
183 for (i
= 0; i
< ProcessData
->HandleTableSize
; i
++)
185 if (ProcessData
->HandleTable
[i
].Object
== NULL
)
190 if (i
>= ProcessData
->HandleTableSize
)
192 Block
= RtlAllocateHeap(Win32CsrApiHeap
,
194 (ProcessData
->HandleTableSize
+ 64) * sizeof(CSRSS_HANDLE
));
197 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
198 return(STATUS_UNSUCCESSFUL
);
201 ProcessData
->HandleTable
,
202 ProcessData
->HandleTableSize
* sizeof(CSRSS_HANDLE
));
203 RtlFreeHeap(Win32CsrApiHeap
, 0, ProcessData
->HandleTable
);
204 ProcessData
->HandleTable
= Block
;
205 ProcessData
->HandleTableSize
+= 64;
207 ProcessData
->HandleTable
[i
].Object
= Object
;
208 ProcessData
->HandleTable
[i
].Access
= Access
;
209 ProcessData
->HandleTable
[i
].Inheritable
= Inheritable
;
210 ProcessData
->HandleTable
[i
].ShareMode
= ShareMode
;
211 Win32CsrCreateHandleEntry(&ProcessData
->HandleTable
[i
]);
212 *Handle
= UlongToHandle((i
<< 2) | 0x3);
213 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
214 return(STATUS_SUCCESS
);
219 Win32CsrDuplicateHandleTable(
220 PCSRSS_PROCESS_DATA SourceProcessData
,
221 PCSRSS_PROCESS_DATA TargetProcessData
)
225 if (TargetProcessData
->HandleTableSize
)
227 return STATUS_INVALID_PARAMETER
;
230 RtlEnterCriticalSection(&SourceProcessData
->HandleTableLock
);
232 /* we are called from CreateProcessData, it isn't necessary to lock the target process data */
234 TargetProcessData
->HandleTable
= RtlAllocateHeap(Win32CsrApiHeap
,
236 SourceProcessData
->HandleTableSize
237 * sizeof(CSRSS_HANDLE
));
238 if (TargetProcessData
->HandleTable
== NULL
)
240 RtlLeaveCriticalSection(&SourceProcessData
->HandleTableLock
);
241 return(STATUS_UNSUCCESSFUL
);
243 TargetProcessData
->HandleTableSize
= SourceProcessData
->HandleTableSize
;
244 for (i
= 0; i
< SourceProcessData
->HandleTableSize
; i
++)
246 if (SourceProcessData
->HandleTable
[i
].Object
!= NULL
&&
247 SourceProcessData
->HandleTable
[i
].Inheritable
)
249 TargetProcessData
->HandleTable
[i
] = SourceProcessData
->HandleTable
[i
];
250 Win32CsrCreateHandleEntry(&TargetProcessData
->HandleTable
[i
]);
253 RtlLeaveCriticalSection(&SourceProcessData
->HandleTableLock
);
254 return(STATUS_SUCCESS
);
257 CSR_API(CsrGetHandle
)
259 NTSTATUS Status
= STATUS_SUCCESS
;
261 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
262 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
264 Request
->Data
.GetInputHandleRequest
.Handle
= INVALID_HANDLE_VALUE
;
266 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
267 if (ProcessData
->Console
)
269 DWORD DesiredAccess
= Request
->Data
.GetInputHandleRequest
.Access
;
270 DWORD ShareMode
= Request
->Data
.GetInputHandleRequest
.ShareMode
;
272 PCSRSS_CONSOLE Console
= ProcessData
->Console
;
275 EnterCriticalSection(&Console
->Lock
);
276 if (Request
->Type
== GET_OUTPUT_HANDLE
)
277 Object
= &Console
->ActiveBuffer
->Header
;
279 Object
= &Console
->Header
;
281 if (((DesiredAccess
& GENERIC_READ
) && Object
->ExclusiveRead
!= 0) ||
282 ((DesiredAccess
& GENERIC_WRITE
) && Object
->ExclusiveWrite
!= 0) ||
283 (!(ShareMode
& FILE_SHARE_READ
) && Object
->AccessRead
!= 0) ||
284 (!(ShareMode
& FILE_SHARE_WRITE
) && Object
->AccessWrite
!= 0))
286 DPRINT1("Sharing violation\n");
287 Status
= STATUS_SHARING_VIOLATION
;
291 Status
= Win32CsrInsertObject(ProcessData
,
292 &Request
->Data
.GetInputHandleRequest
.Handle
,
295 Request
->Data
.GetInputHandleRequest
.Inheritable
,
298 LeaveCriticalSection(&Console
->Lock
);
300 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
305 CSR_API(CsrCloseHandle
)
307 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
308 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
310 return Win32CsrReleaseObject(ProcessData
, Request
->Data
.CloseHandleRequest
.Handle
);
313 CSR_API(CsrVerifyHandle
)
316 NTSTATUS Status
= STATUS_SUCCESS
;
318 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
319 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
321 Index
= (ULONG_PTR
)Request
->Data
.VerifyHandleRequest
.Handle
>> 2;
322 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
323 if (Index
>= ProcessData
->HandleTableSize
||
324 ProcessData
->HandleTable
[Index
].Object
== NULL
)
326 DPRINT("CsrVerifyObject failed\n");
327 Status
= STATUS_INVALID_HANDLE
;
329 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
334 CSR_API(CsrDuplicateHandle
)
340 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
341 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
343 Index
= (ULONG_PTR
)Request
->Data
.DuplicateHandleRequest
.Handle
>> 2;
344 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
345 if (Index
>= ProcessData
->HandleTableSize
346 || (Entry
= &ProcessData
->HandleTable
[Index
])->Object
== NULL
)
348 DPRINT1("Couldn't dup invalid handle %p\n", Request
->Data
.DuplicateHandleRequest
.Handle
);
349 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
350 return STATUS_INVALID_HANDLE
;
353 if (Request
->Data
.DuplicateHandleRequest
.Options
& DUPLICATE_SAME_ACCESS
)
355 DesiredAccess
= Entry
->Access
;
359 DesiredAccess
= Request
->Data
.DuplicateHandleRequest
.Access
;
360 /* Make sure the source handle has all the desired flags */
361 if (~Entry
->Access
& DesiredAccess
)
363 DPRINT1("Handle %p only has access %X; requested %X\n",
364 Request
->Data
.DuplicateHandleRequest
.Handle
, Entry
->Access
, DesiredAccess
);
365 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
366 return STATUS_INVALID_PARAMETER
;
370 Request
->Status
= Win32CsrInsertObject(ProcessData
,
371 &Request
->Data
.DuplicateHandleRequest
.Handle
,
374 Request
->Data
.DuplicateHandleRequest
.Inheritable
,
376 if (NT_SUCCESS(Request
->Status
)
377 && Request
->Data
.DuplicateHandleRequest
.Options
& DUPLICATE_CLOSE_SOURCE
)
379 Win32CsrCloseHandleEntry(Entry
);
382 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
383 return Request
->Status
;
386 CSR_API(CsrGetInputWaitHandle
)
388 Request
->Header
.u1
.s1
.TotalLength
= sizeof(CSR_API_MESSAGE
);
389 Request
->Header
.u1
.s1
.DataLength
= sizeof(CSR_API_MESSAGE
) - sizeof(PORT_MESSAGE
);
391 Request
->Data
.GetConsoleInputWaitHandle
.InputWaitHandle
= ProcessData
->ConsoleEvent
;
392 return STATUS_SUCCESS
;