1 /* $Id: handle.c 57570 2012-10-17 23:10:40Z hbelusca $
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(PCSRSS_HANDLE Entry
)
41 Object_t
*Object
= Entry
->Object
;
42 EnterCriticalSection(&Object
->Console
->Lock
);
43 AdjustHandleCounts(Entry
, +1);
44 LeaveCriticalSection(&Object
->Console
->Lock
);
48 Win32CsrCloseHandleEntry(PCSRSS_HANDLE Entry
)
50 Object_t
*Object
= Entry
->Object
;
53 PCSRSS_CONSOLE Console
= Object
->Console
;
54 EnterCriticalSection(&Console
->Lock
);
55 /* If the last handle to a screen buffer is closed, delete it */
56 if (AdjustHandleCounts(Entry
, -1) == 0
57 && Object
->Type
== CONIO_SCREEN_BUFFER_MAGIC
)
59 PCSRSS_SCREEN_BUFFER Buffer
= (PCSRSS_SCREEN_BUFFER
)Object
;
60 /* ...unless it's the only buffer left. Windows allows deletion
61 * even of the last buffer, but having to deal with a lack of
62 * any active buffer might be error-prone. */
63 if (Buffer
->ListEntry
.Flink
!= Buffer
->ListEntry
.Blink
)
64 ConioDeleteScreenBuffer(Buffer
);
66 LeaveCriticalSection(&Console
->Lock
);
73 Win32CsrReleaseObject(PCSR_PROCESS ProcessData
,
76 ULONG_PTR h
= (ULONG_PTR
)Handle
>> 2;
79 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
80 if (h
>= ProcessData
->HandleTableSize
81 || (Object
= ProcessData
->HandleTable
[h
].Object
) == NULL
)
83 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
84 return STATUS_INVALID_HANDLE
;
86 Win32CsrCloseHandleEntry(&ProcessData
->HandleTable
[h
]);
87 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
88 return STATUS_SUCCESS
;
93 Win32CsrLockObject(PCSR_PROCESS ProcessData
,
99 ULONG_PTR h
= (ULONG_PTR
)Handle
>> 2;
101 DPRINT("CsrGetObject, Object: %x, %x, %x\n",
102 Object
, Handle
, ProcessData
? ProcessData
->HandleTableSize
: 0);
104 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
105 if (!CsrIsConsoleHandle(Handle
) || h
>= ProcessData
->HandleTableSize
106 || (*Object
= ProcessData
->HandleTable
[h
].Object
) == NULL
107 || ~ProcessData
->HandleTable
[h
].Access
& Access
108 || (Type
!= 0 && (*Object
)->Type
!= Type
))
110 DPRINT1("CsrGetObject returning invalid handle (%x)\n", Handle
);
111 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
112 return STATUS_INVALID_HANDLE
;
114 _InterlockedIncrement(&(*Object
)->Console
->ReferenceCount
);
115 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
117 EnterCriticalSection(&((*Object
)->Console
->Lock
));
118 return STATUS_SUCCESS
;
123 Win32CsrUnlockObject(Object_t
*Object
)
125 PCSRSS_CONSOLE Console
= Object
->Console
;
126 LeaveCriticalSection(&Console
->Lock
);
128 if (_InterlockedDecrement(&Console
->ReferenceCount
) == 0)
129 ConioDeleteConsole(&Console
->Header
);
134 Win32CsrReleaseConsole(PCSR_PROCESS ProcessData
)
136 PCSRSS_CONSOLE Console
;
139 /* Close all console handles and detach process from console */
140 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
142 for (i
= 0; i
< ProcessData
->HandleTableSize
; i
++)
143 Win32CsrCloseHandleEntry(&ProcessData
->HandleTable
[i
]);
144 ProcessData
->HandleTableSize
= 0;
145 RtlFreeHeap(ConSrvHeap
, 0, ProcessData
->HandleTable
);
146 ProcessData
->HandleTable
= NULL
;
148 Console
= ProcessData
->Console
;
151 ProcessData
->Console
= NULL
;
152 EnterCriticalSection(&Console
->Lock
);
153 RemoveEntryList(&ProcessData
->ConsoleLink
);
154 LeaveCriticalSection(&Console
->Lock
);
155 if (_InterlockedDecrement(&Console
->ReferenceCount
) == 0)
156 ConioDeleteConsole(&Console
->Header
);
157 //CloseHandle(ProcessData->ConsoleEvent);
158 //ProcessData->ConsoleEvent = NULL;
160 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
165 Win32CsrInsertObject(PCSR_PROCESS ProcessData
,
175 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
177 for (i
= 0; i
< ProcessData
->HandleTableSize
; i
++)
179 if (ProcessData
->HandleTable
[i
].Object
== NULL
)
184 if (i
>= ProcessData
->HandleTableSize
)
186 Block
= RtlAllocateHeap(ConSrvHeap
,
188 (ProcessData
->HandleTableSize
+ 64) * sizeof(CSRSS_HANDLE
));
191 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
192 return(STATUS_UNSUCCESSFUL
);
195 ProcessData
->HandleTable
,
196 ProcessData
->HandleTableSize
* sizeof(CSRSS_HANDLE
));
197 RtlFreeHeap(ConSrvHeap
, 0, ProcessData
->HandleTable
);
198 ProcessData
->HandleTable
= Block
;
199 ProcessData
->HandleTableSize
+= 64;
201 ProcessData
->HandleTable
[i
].Object
= Object
;
202 ProcessData
->HandleTable
[i
].Access
= Access
;
203 ProcessData
->HandleTable
[i
].Inheritable
= Inheritable
;
204 ProcessData
->HandleTable
[i
].ShareMode
= ShareMode
;
205 Win32CsrCreateHandleEntry(&ProcessData
->HandleTable
[i
]);
206 *Handle
= UlongToHandle((i
<< 2) | 0x3);
207 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
208 return(STATUS_SUCCESS
);
213 Win32CsrDuplicateHandleTable(PCSR_PROCESS SourceProcessData
,
214 PCSR_PROCESS TargetProcessData
)
218 /* Only inherit if the flag was set */
219 if (!TargetProcessData
->bInheritHandles
) return STATUS_SUCCESS
;
221 if (TargetProcessData
->HandleTableSize
)
223 return STATUS_INVALID_PARAMETER
;
226 RtlEnterCriticalSection(&SourceProcessData
->HandleTableLock
);
228 /* we are called from CreateProcessData, it isn't necessary to lock the target process data */
230 TargetProcessData
->HandleTable
= RtlAllocateHeap(ConSrvHeap
,
232 SourceProcessData
->HandleTableSize
233 * sizeof(CSRSS_HANDLE
));
234 if (TargetProcessData
->HandleTable
== NULL
)
236 RtlLeaveCriticalSection(&SourceProcessData
->HandleTableLock
);
237 return(STATUS_UNSUCCESSFUL
);
239 TargetProcessData
->HandleTableSize
= SourceProcessData
->HandleTableSize
;
240 for (i
= 0; i
< SourceProcessData
->HandleTableSize
; i
++)
242 if (SourceProcessData
->HandleTable
[i
].Object
!= NULL
&&
243 SourceProcessData
->HandleTable
[i
].Inheritable
)
245 TargetProcessData
->HandleTable
[i
] = SourceProcessData
->HandleTable
[i
];
246 Win32CsrCreateHandleEntry(&TargetProcessData
->HandleTable
[i
]);
249 RtlLeaveCriticalSection(&SourceProcessData
->HandleTableLock
);
250 return(STATUS_SUCCESS
);
253 CSR_API(CsrGetHandle
)
255 NTSTATUS Status
= STATUS_SUCCESS
;
256 PCSR_PROCESS ProcessData
= CsrGetClientThread()->Process
;
258 ApiMessage
->Data
.GetInputHandleRequest
.Handle
= INVALID_HANDLE_VALUE
;
260 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
261 if (ProcessData
->Console
)
263 DWORD DesiredAccess
= ApiMessage
->Data
.GetInputHandleRequest
.Access
;
264 DWORD ShareMode
= ApiMessage
->Data
.GetInputHandleRequest
.ShareMode
;
266 PCSRSS_CONSOLE Console
= ProcessData
->Console
;
269 EnterCriticalSection(&Console
->Lock
);
270 if (ApiMessage
->ApiNumber
== GET_OUTPUT_HANDLE
)
271 Object
= &Console
->ActiveBuffer
->Header
;
273 Object
= &Console
->Header
;
275 if (((DesiredAccess
& GENERIC_READ
) && Object
->ExclusiveRead
!= 0) ||
276 ((DesiredAccess
& GENERIC_WRITE
) && Object
->ExclusiveWrite
!= 0) ||
277 (!(ShareMode
& FILE_SHARE_READ
) && Object
->AccessRead
!= 0) ||
278 (!(ShareMode
& FILE_SHARE_WRITE
) && Object
->AccessWrite
!= 0))
280 DPRINT1("Sharing violation\n");
281 Status
= STATUS_SHARING_VIOLATION
;
285 Status
= Win32CsrInsertObject(ProcessData
,
286 &ApiMessage
->Data
.GetInputHandleRequest
.Handle
,
289 ApiMessage
->Data
.GetInputHandleRequest
.Inheritable
,
292 LeaveCriticalSection(&Console
->Lock
);
294 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
299 // CSR_API(CsrSetHandle) ??
301 CSR_API(SrvCloseHandle
)
303 return Win32CsrReleaseObject(CsrGetClientThread()->Process
, ApiMessage
->Data
.CloseHandleRequest
.Handle
);
306 CSR_API(SrvVerifyConsoleIoHandle
)
309 NTSTATUS Status
= STATUS_SUCCESS
;
310 PCSR_PROCESS ProcessData
= CsrGetClientThread()->Process
;
312 Index
= (ULONG_PTR
)ApiMessage
->Data
.VerifyHandleRequest
.Handle
>> 2;
313 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
314 if (Index
>= ProcessData
->HandleTableSize
||
315 ProcessData
->HandleTable
[Index
].Object
== NULL
)
317 DPRINT("CsrVerifyObject failed\n");
318 Status
= STATUS_INVALID_HANDLE
;
320 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
325 CSR_API(SrvDuplicateHandle
)
330 PCSR_PROCESS ProcessData
= CsrGetClientThread()->Process
;
332 Index
= (ULONG_PTR
)ApiMessage
->Data
.DuplicateHandleRequest
.Handle
>> 2;
333 RtlEnterCriticalSection(&ProcessData
->HandleTableLock
);
334 if (Index
>= ProcessData
->HandleTableSize
335 || (Entry
= &ProcessData
->HandleTable
[Index
])->Object
== NULL
)
337 DPRINT1("Couldn't dup invalid handle %p\n", ApiMessage
->Data
.DuplicateHandleRequest
.Handle
);
338 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
339 return STATUS_INVALID_HANDLE
;
342 if (ApiMessage
->Data
.DuplicateHandleRequest
.Options
& DUPLICATE_SAME_ACCESS
)
344 DesiredAccess
= Entry
->Access
;
348 DesiredAccess
= ApiMessage
->Data
.DuplicateHandleRequest
.Access
;
349 /* Make sure the source handle has all the desired flags */
350 if (~Entry
->Access
& DesiredAccess
)
352 DPRINT1("Handle %p only has access %X; requested %X\n",
353 ApiMessage
->Data
.DuplicateHandleRequest
.Handle
, Entry
->Access
, DesiredAccess
);
354 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
355 return STATUS_INVALID_PARAMETER
;
359 ApiMessage
->Status
= Win32CsrInsertObject(ProcessData
,
360 &ApiMessage
->Data
.DuplicateHandleRequest
.Handle
,
363 ApiMessage
->Data
.DuplicateHandleRequest
.Inheritable
,
365 if (NT_SUCCESS(ApiMessage
->Status
)
366 && ApiMessage
->Data
.DuplicateHandleRequest
.Options
& DUPLICATE_CLOSE_SOURCE
)
368 Win32CsrCloseHandleEntry(Entry
);
371 RtlLeaveCriticalSection(&ProcessData
->HandleTableLock
);
372 return ApiMessage
->Status
;
375 CSR_API(CsrGetInputWaitHandle
)
377 ApiMessage
->Data
.GetConsoleInputWaitHandle
.InputWaitHandle
= CsrGetClientThread()->Process
->ConsoleEvent
;
378 return STATUS_SUCCESS
;