2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ob/wait.c
5 * PURPOSE: Handles Waiting on Objects
7 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) - Created file
8 * David Welch (welch@mcmail.com)
11 /* INCLUDES ******************************************************************/
15 #include <internal/debug.h>
17 /* FUNCTIONS *****************************************************************/
19 BOOL
inline FASTCALL
KiIsObjectWaitable(PVOID Object
);
22 NtWaitForMultipleObjects(IN ULONG ObjectCount
,
23 IN PHANDLE ObjectsArray
,
24 IN WAIT_TYPE WaitType
,
26 IN PLARGE_INTEGER TimeOut OPTIONAL
)
28 KWAIT_BLOCK WaitBlockArray
[MAXIMUM_WAIT_OBJECTS
];
29 HANDLE SafeObjectsArray
[MAXIMUM_WAIT_OBJECTS
];
30 PVOID ObjectPtrArray
[MAXIMUM_WAIT_OBJECTS
];
32 KPROCESSOR_MODE PreviousMode
;
33 LARGE_INTEGER SafeTimeOut
;
34 NTSTATUS Status
= STATUS_SUCCESS
;
36 DPRINT("NtWaitForMultipleObjects(ObjectCount %lu ObjectsArray[] %x, Alertable %d, "
37 "TimeOut %x)\n", ObjectCount
,ObjectsArray
,Alertable
,TimeOut
);
39 PreviousMode
= ExGetPreviousMode();
41 if (ObjectCount
> MAXIMUM_WAIT_OBJECTS
)
42 return STATUS_UNSUCCESSFUL
;
44 return STATUS_INVALID_PARAMETER
;
46 if(PreviousMode
!= KernelMode
)
50 ProbeForRead(ObjectsArray
,
51 ObjectCount
* sizeof(ObjectsArray
[0]),
53 /* make a copy so we don't have to guard with SEH later and keep track of
54 what objects we referenced in case dereferencing pointers suddenly fails */
55 RtlCopyMemory(SafeObjectsArray
, ObjectsArray
, ObjectCount
* sizeof(ObjectsArray
[0]));
56 ObjectsArray
= SafeObjectsArray
;
61 sizeof(LARGE_INTEGER
),
63 /* make a local copy of the timeout on the stack */
64 SafeTimeOut
= *TimeOut
;
65 TimeOut
= &SafeTimeOut
;
70 Status
= _SEH_GetExceptionCode();
74 if(!NT_SUCCESS(Status
))
80 /* reference all objects */
81 for (i
= 0; i
< ObjectCount
; i
++)
83 Status
= ObReferenceObjectByHandle(ObjectsArray
[i
],
89 if (!NT_SUCCESS(Status
) || !KiIsObjectWaitable(ObjectPtrArray
[i
]))
91 if (NT_SUCCESS(Status
))
93 DPRINT1("Waiting for object type '%wZ' is not supported\n",
94 &BODY_TO_HEADER(ObjectPtrArray
[i
])->Type
->Name
);
95 Status
= STATUS_INVALID_HANDLE
;
98 /* dereference all referenced objects */
99 for (j
= 0; j
< i
; j
++)
101 ObDereferenceObject(ObjectPtrArray
[j
]);
108 Status
= KeWaitForMultipleObjects(ObjectCount
,
117 /* dereference all objects */
118 for (i
= 0; i
< ObjectCount
; i
++)
120 ObDereferenceObject(ObjectPtrArray
[i
]);
131 NtWaitForSingleObject(IN HANDLE ObjectHandle
,
132 IN BOOLEAN Alertable
,
133 IN PLARGE_INTEGER TimeOut OPTIONAL
)
136 KPROCESSOR_MODE PreviousMode
;
137 LARGE_INTEGER SafeTimeOut
;
138 NTSTATUS Status
= STATUS_SUCCESS
;
140 DPRINT("NtWaitForSingleObject(ObjectHandle %x, Alertable %d, TimeOut %x)\n",
141 ObjectHandle
,Alertable
,TimeOut
);
143 PreviousMode
= ExGetPreviousMode();
145 if(TimeOut
!= NULL
&& PreviousMode
!= KernelMode
)
149 ProbeForRead(TimeOut
,
150 sizeof(LARGE_INTEGER
),
152 /* make a copy on the stack */
153 SafeTimeOut
= *TimeOut
;
154 TimeOut
= &SafeTimeOut
;
158 Status
= _SEH_GetExceptionCode();
162 if(!NT_SUCCESS(Status
))
168 Status
= ObReferenceObjectByHandle(ObjectHandle
,
174 if (!NT_SUCCESS(Status
))
178 if (!KiIsObjectWaitable(ObjectPtr
))
180 DPRINT1("Waiting for object type '%wZ' is not supported\n",
181 &BODY_TO_HEADER(ObjectPtr
)->Type
->Name
);
182 Status
= STATUS_INVALID_HANDLE
;
186 Status
= KeWaitForSingleObject(ObjectPtr
,
193 ObDereferenceObject(ObjectPtr
);
201 NtSignalAndWaitForSingleObject(IN HANDLE ObjectHandleToSignal
,
202 IN HANDLE WaitableObjectHandle
,
203 IN BOOLEAN Alertable
,
204 IN PLARGE_INTEGER TimeOut OPTIONAL
)
206 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
207 PDISPATCHER_HEADER Header
;
210 LARGE_INTEGER SafeTimeOut
;
211 OBJECT_HANDLE_INFORMATION HandleInfo
;
212 NTSTATUS Status
= STATUS_SUCCESS
;
214 /* Capture timeout */
215 if(!TimeOut
&& PreviousMode
!= KernelMode
)
219 ProbeForRead(TimeOut
,
220 sizeof(LARGE_INTEGER
),
222 /* Make a copy on the stack */
223 SafeTimeOut
= *TimeOut
;
224 TimeOut
= &SafeTimeOut
;
228 Status
= _SEH_GetExceptionCode();
232 if(!NT_SUCCESS(Status
)) return Status
;
235 /* Start by getting the signal object*/
236 Status
= ObReferenceObjectByHandle(ObjectHandleToSignal
,
242 if (!NT_SUCCESS(Status
))
247 /* Now get the wait object */
248 Status
= ObReferenceObjectByHandle(WaitableObjectHandle
,
254 if (!NT_SUCCESS(Status
))
256 ObDereferenceObject(SignalObj
);
260 /* FIXME: Use DefaultObject from ObjectHeader */
261 Header
= (PDISPATCHER_HEADER
)SignalObj
;
263 /* Check dispatcher type */
264 /* FIXME: Check Object Type instead! */
265 switch (Header
->Type
)
267 case EventNotificationObject
:
268 case EventSynchronizationObject
:
270 /* FIXME: Check permissions */
271 KeSetEvent(SignalObj
, EVENT_INCREMENT
, TRUE
);
275 /* Release the Mutant. This can raise an exception*/
278 KeReleaseMutant(SignalObj
, MUTANT_INCREMENT
, FALSE
, TRUE
);
282 Status
= _SEH_GetExceptionCode();
288 case SemaphoreObject
:
289 /* Release the Semaphore. This can raise an exception*/
290 /* FIXME: Check permissions */
293 KeReleaseSemaphore(SignalObj
, SEMAPHORE_INCREMENT
, 1, TRUE
);
297 Status
= _SEH_GetExceptionCode();
304 Status
= STATUS_OBJECT_TYPE_MISMATCH
;
308 /* Now wait. Also SEH this since it can also raise an exception */
311 Status
= KeWaitForSingleObject(WaitObj
,
319 Status
= _SEH_GetExceptionCode();
323 /* We're done here */
325 ObDereferenceObject(SignalObj
);
326 ObDereferenceObject(WaitObj
);