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
])->ObjectType
->TypeName
);
95 Status
= STATUS_HANDLE_NOT_WAITABLE
;
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
)->ObjectType
->TypeName
);
182 Status
= STATUS_HANDLE_NOT_WAITABLE
;
186 Status
= KeWaitForSingleObject(ObjectPtr
,
193 ObDereferenceObject(ObjectPtr
);
200 NtSignalAndWaitForSingleObject(IN HANDLE ObjectHandleToSignal
,
201 IN HANDLE WaitableObjectHandle
,
202 IN BOOLEAN Alertable
,
203 IN PLARGE_INTEGER TimeOut OPTIONAL
)
205 KPROCESSOR_MODE PreviousMode
;
206 DISPATCHER_HEADER
* hdr
;
209 LARGE_INTEGER SafeTimeOut
;
210 NTSTATUS Status
= STATUS_SUCCESS
;
212 PreviousMode
= ExGetPreviousMode();
214 if(TimeOut
!= NULL
&& PreviousMode
!= KernelMode
)
218 ProbeForRead(TimeOut
,
219 sizeof(LARGE_INTEGER
),
221 /* make a copy on the stack */
222 SafeTimeOut
= *TimeOut
;
223 TimeOut
= &SafeTimeOut
;
227 Status
= _SEH_GetExceptionCode();
231 if(!NT_SUCCESS(Status
))
237 Status
= ObReferenceObjectByHandle(ObjectHandleToSignal
,
243 if (!NT_SUCCESS(Status
))
248 Status
= ObReferenceObjectByHandle(WaitableObjectHandle
,
254 if (!NT_SUCCESS(Status
))
256 ObDereferenceObject(SignalObj
);
260 hdr
= (DISPATCHER_HEADER
*)SignalObj
;
263 case EventNotificationObject
:
264 case EventSynchronizationObject
:
265 KeSetEvent(SignalObj
,
271 KeReleaseMutex(SignalObj
,
275 case SemaphoreObject
:
276 KeReleaseSemaphore(SignalObj
,
283 ObDereferenceObject(SignalObj
);
284 ObDereferenceObject(WaitObj
);
285 return STATUS_OBJECT_TYPE_MISMATCH
;
288 Status
= KeWaitForSingleObject(WaitObj
,
294 ObDereferenceObject(SignalObj
);
295 ObDereferenceObject(WaitObj
);