Forgot this file.
Added: trunk/reactos/ntoskrnl/ob/wait.c

Added: trunk/reactos/ntoskrnl/ob/wait.c
--- trunk/reactos/ntoskrnl/ob/wait.c	2005-03-14 05:54:32 UTC (rev 14047)
+++ trunk/reactos/ntoskrnl/ob/wait.c	2005-03-14 05:54:58 UTC (rev 14048)
@@ -0,0 +1,300 @@
+/*
+ * COPYRIGHT:          See COPYING in the top level directory
+ * PROJECT:            ReactOS kernel
+ * FILE:               ntoskrnl/ob/wait.c
+ * PURPOSE:            Handles Waiting on Objects
+ * 
+ * PROGRAMMERS:        Alex Ionescu (alex@relsoft.net) - Created file
+ *                     David Welch (welch@mcmail.com)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <ntoskrnl.h>
+#define NDEBUG
+#include <internal/debug.h>
+
+/* FUNCTIONS *****************************************************************/
+
+BOOL inline FASTCALL KiIsObjectWaitable(PVOID Object);
+
+NTSTATUS STDCALL
+NtWaitForMultipleObjects(IN ULONG ObjectCount,
+			 IN PHANDLE ObjectsArray,
+			 IN WAIT_TYPE WaitType,
+			 IN BOOLEAN Alertable,
+			 IN PLARGE_INTEGER TimeOut  OPTIONAL)
+{
+   KWAIT_BLOCK WaitBlockArray[MAXIMUM_WAIT_OBJECTS];
+   HANDLE SafeObjectsArray[MAXIMUM_WAIT_OBJECTS];
+   PVOID ObjectPtrArray[MAXIMUM_WAIT_OBJECTS];
+   ULONG i, j;
+   KPROCESSOR_MODE PreviousMode;
+   LARGE_INTEGER SafeTimeOut;
+   NTSTATUS Status = STATUS_SUCCESS;
+
+   DPRINT("NtWaitForMultipleObjects(ObjectCount %lu ObjectsArray[] %x, Alertable %d, "
+	  "TimeOut %x)\n", ObjectCount,ObjectsArray,Alertable,TimeOut);
+
+   PreviousMode = ExGetPreviousMode();
+
+   if (ObjectCount > MAXIMUM_WAIT_OBJECTS)
+     return STATUS_UNSUCCESSFUL;
+   if (0 == ObjectCount)
+     return STATUS_INVALID_PARAMETER;
+
+   if(PreviousMode != KernelMode)
+   {
+     _SEH_TRY
+     {
+       ProbeForRead(ObjectsArray,
+                    ObjectCount * sizeof(ObjectsArray[0]),
+                    sizeof(ULONG));
+       /* make a copy so we don't have to guard with SEH later and keep track of
+          what objects we referenced in case dereferencing pointers suddenly fails */
+       RtlCopyMemory(SafeObjectsArray, ObjectsArray, ObjectCount * sizeof(ObjectsArray[0]));
+       ObjectsArray = SafeObjectsArray;
+       
+       if(TimeOut != NULL)
+       {
+         ProbeForRead(TimeOut,
+                      sizeof(LARGE_INTEGER),
+                      sizeof(ULONG));
+         /* make a local copy of the timeout on the stack */
+         SafeTimeOut = *TimeOut;
+         TimeOut = &SafeTimeOut;
+       }
+     }
+     _SEH_HANDLE
+     {
+       Status = _SEH_GetExceptionCode();
+     }
+     _SEH_END;
+     
+     if(!NT_SUCCESS(Status))
+     {
+       return Status;
+     }
+   }
+
+   /* reference all objects */
+   for (i = 0; i < ObjectCount; i++)
+     {
+        Status = ObReferenceObjectByHandle(ObjectsArray[i],
+                                           SYNCHRONIZE,
+                                           NULL,
+                                           PreviousMode,
+                                           &ObjectPtrArray[i],
+                                           NULL);
+        if (!NT_SUCCESS(Status) || !KiIsObjectWaitable(ObjectPtrArray[i]))
+          {
+             if (NT_SUCCESS(Status))
+	       {
+	         DPRINT1("Waiting for object type '%wZ' is not supported\n", 
+		         &BODY_TO_HEADER(ObjectPtrArray[i])->ObjectType->TypeName);
+	         Status = STATUS_HANDLE_NOT_WAITABLE;
+		 i++;
+	       }
+             /* dereference all referenced objects */
+             for (j = 0; j < i; j++)
+               {
+                  ObDereferenceObject(ObjectPtrArray[j]);
+               }
+
+             return(Status);
+          }
+     }
+
+   Status = KeWaitForMultipleObjects(ObjectCount,
+                                     ObjectPtrArray,
+                                     WaitType,
+                                     UserRequest,
+                                     PreviousMode,
+                                     Alertable,
+				     TimeOut,
+                                     WaitBlockArray);
+
+   /* dereference all objects */
+   for (i = 0; i < ObjectCount; i++)
+     {
+        ObDereferenceObject(ObjectPtrArray[i]);
+     }
+
+   return(Status);
+}
+
+
+/*
+ * @implemented
+ */
+NTSTATUS STDCALL
+NtWaitForSingleObject(IN HANDLE ObjectHandle,
+		      IN BOOLEAN Alertable,
+		      IN PLARGE_INTEGER TimeOut  OPTIONAL)
+{
+   PVOID ObjectPtr;
+   KPROCESSOR_MODE PreviousMode;
+   LARGE_INTEGER SafeTimeOut;
+   NTSTATUS Status = STATUS_SUCCESS;
+
+   DPRINT("NtWaitForSingleObject(ObjectHandle %x, Alertable %d, TimeOut %x)\n",
+	  ObjectHandle,Alertable,TimeOut);
+
+   PreviousMode = ExGetPreviousMode();
+   
+   if(TimeOut != NULL && PreviousMode != KernelMode)
+   {
+     _SEH_TRY
+     {
+       ProbeForRead(TimeOut,
+                    sizeof(LARGE_INTEGER),
+                    sizeof(ULONG));
+       /* make a copy on the stack */
+       SafeTimeOut = *TimeOut;
+       TimeOut = &SafeTimeOut;
+     }
+     _SEH_HANDLE
+     {
+       Status = _SEH_GetExceptionCode();
+     }
+     _SEH_END;
+     
+     if(!NT_SUCCESS(Status))
+     {
+       return Status;
+     }
+   }
+
+   Status = ObReferenceObjectByHandle(ObjectHandle,
+				      SYNCHRONIZE,
+				      NULL,
+				      PreviousMode,
+				      &ObjectPtr,
+				      NULL);
+   if (!NT_SUCCESS(Status))
+     {
+	return(Status);
+     }
+   if (!KiIsObjectWaitable(ObjectPtr))
+     {
+       DPRINT1("Waiting for object type '%wZ' is not supported\n", 
+	       &BODY_TO_HEADER(ObjectPtr)->ObjectType->TypeName);
+       Status = STATUS_HANDLE_NOT_WAITABLE;
+     }
+   else
+     {
+       Status = KeWaitForSingleObject(ObjectPtr,
+				      UserRequest,
+				      PreviousMode,
+				      Alertable,
+				      TimeOut);
+     }
+
+   ObDereferenceObject(ObjectPtr);
+
+   return(Status);
+}
+
+
+NTSTATUS STDCALL
+NtSignalAndWaitForSingleObject(IN HANDLE ObjectHandleToSignal,
+			       IN HANDLE WaitableObjectHandle,
+			       IN BOOLEAN Alertable,
+			       IN PLARGE_INTEGER TimeOut  OPTIONAL)
+{
+   KPROCESSOR_MODE PreviousMode;
+   DISPATCHER_HEADER* hdr;
+   PVOID SignalObj;
+   PVOID WaitObj;
+   LARGE_INTEGER SafeTimeOut;
+   NTSTATUS Status = STATUS_SUCCESS;
+
+   PreviousMode = ExGetPreviousMode();
+   
+   if(TimeOut != NULL && PreviousMode != KernelMode)
+   {
+     _SEH_TRY
+     {
+       ProbeForRead(TimeOut,
+                    sizeof(LARGE_INTEGER),
+                    sizeof(ULONG));
+       /* make a copy on the stack */
+       SafeTimeOut = *TimeOut;
+       TimeOut = &SafeTimeOut;
+     }
+     _SEH_HANDLE
+     {
+       Status = _SEH_GetExceptionCode();
+     }
+     _SEH_END;
+     
+     if(!NT_SUCCESS(Status))
+     {
+       return Status;
+     }
+   }
+   
+   Status = ObReferenceObjectByHandle(ObjectHandleToSignal,
+				      0,
+				      NULL,
+				      PreviousMode,
+				      &SignalObj,
+				      NULL);
+   if (!NT_SUCCESS(Status))
+     {
+	return Status;
+     }
+
+   Status = ObReferenceObjectByHandle(WaitableObjectHandle,
+				      SYNCHRONIZE,
+				      NULL,
+				      PreviousMode,
+				      &WaitObj,
+				      NULL);
+   if (!NT_SUCCESS(Status))
+     {
+	ObDereferenceObject(SignalObj);
+	return Status;
+     }
+
+   hdr = (DISPATCHER_HEADER *)SignalObj;
+   switch (hdr->Type)
+     {
+      case EventNotificationObject:
+      case EventSynchronizationObject:
+	KeSetEvent(SignalObj,
+		   EVENT_INCREMENT,
+		   TRUE);
+	break;
+
+      case MutantObject:
+	KeReleaseMutex(SignalObj,
+		       TRUE);
+	break;
+
+      case SemaphoreObject:
+	KeReleaseSemaphore(SignalObj,
+			   SEMAPHORE_INCREMENT,
+			   1,
+			   TRUE);
+	break;
+
+      default:
+	ObDereferenceObject(SignalObj);
+	ObDereferenceObject(WaitObj);
+	return STATUS_OBJECT_TYPE_MISMATCH;
+     }
+
+   Status = KeWaitForSingleObject(WaitObj,
+				  UserRequest,
+				  PreviousMode,
+				  Alertable,
+				  TimeOut);
+
+   ObDereferenceObject(SignalObj);
+   ObDereferenceObject(WaitObj);
+
+   return Status;
+}
+
+/* EOF */