secured access to buffers in NtWaitForSingleObject(), NtWaitForMultipleObjects() and NtSignalAndWaitForSingleObject()
Modified: trunk/reactos/include/ntos/zw.h
Modified: trunk/reactos/ntoskrnl/ke/wait.c
Modified: trunk/reactos/w32api/include/ddk/winddk.h

Modified: trunk/reactos/include/ntos/zw.h
--- trunk/reactos/include/ntos/zw.h	2005-02-14 21:41:49 UTC (rev 13578)
+++ trunk/reactos/include/ntos/zw.h	2005-02-14 22:50:15 UTC (rev 13579)
@@ -4423,28 +4423,28 @@
 /*
  * FUNCTION: Signals an object and wait for an other one.
  * ARGUMENTS: 
- *        SignalObject = Handle to the object that should be signaled
- *        WaitObject = Handle to the object that should be waited for
+ *        ObjectHandleToSignal = Handle to the object that should be signaled
+ *        WaitableObjectHandle = Handle to the object that should be waited for
  *        Alertable = True if the wait is alertable
- *        Time = The time to wait
+ *        TimeOut = The time to wait
  * RETURNS: Status
  */
 NTSTATUS
 STDCALL
 NtSignalAndWaitForSingleObject(
-	IN	HANDLE		SignalObject,
-	IN	HANDLE		WaitObject,
+	IN	HANDLE		ObjectHandleToSignal,
+	IN	HANDLE		WaitableObjectHandle,
 	IN	BOOLEAN		Alertable,
-	IN	PLARGE_INTEGER	Time
+	IN	PLARGE_INTEGER	TimeOut  OPTIONAL
 	);
 
 NTSTATUS
 STDCALL
 NtSignalAndWaitForSingleObject(
-	IN	HANDLE		SignalObject,
-	IN	HANDLE		WaitObject,
+	IN	HANDLE		ObjectHandleToSignal,
+	IN	HANDLE		WaitableObjectHandle,
 	IN	BOOLEAN		Alertable,
-	IN	PLARGE_INTEGER	Time
+	IN	PLARGE_INTEGER	TimeOut  OPTIONAL
 	);
 
 /*
@@ -4651,9 +4651,9 @@
 /*
  * FUNCTION: Waits for an object to become signalled.
  * ARGUMENTS: 
- *       Object = The object handle
+ *       ObjectHandle = The object handle
  *       Alertable = If true the wait is alertable.
- *       Time = The maximum wait time.
+ *       TimeOut = The maximum wait time.
  * REMARKS:
  *       This function maps to the win32 WaitForSingleObjectEx.
  * RETURNS: Status
@@ -4661,17 +4661,17 @@
 NTSTATUS
 STDCALL
 NtWaitForSingleObject (
-	IN HANDLE Object,
+	IN HANDLE ObjectHandle,
 	IN BOOLEAN Alertable,
-	IN PLARGE_INTEGER Time
+	IN PLARGE_INTEGER TimeOut  OPTIONAL
 	);
 
 NTSTATUS
 STDCALL
 ZwWaitForSingleObject (
-	IN HANDLE Object,
+	IN HANDLE ObjectHandle,
 	IN BOOLEAN Alertable,
-	IN PLARGE_INTEGER Time
+	IN PLARGE_INTEGER TimeOut  OPTIONAL
 	);
 
 /* --- EVENT PAIR OBJECT --- */
@@ -5583,11 +5583,11 @@
 /*
  * FUNCTION: Waits for multiple objects to become signalled.
  * ARGUMENTS: 
- *       Count = The number of objects
- *       Object = The array of object handles
+ *       ObjectCount = The number of objects
+ *       ObjectsArray = The array of object handles
  *       WaitType = Can be one of the values UserMode or KernelMode
  *       Alertable = If true the wait is alertable.
- *       Time = The maximum wait time.
+ *       TimeOut = The maximum wait time.
  * REMARKS:
  *       This function maps to the win32 WaitForMultipleObjectEx.
  * RETURNS: Status
@@ -5595,11 +5595,11 @@
 NTSTATUS
 STDCALL
 NtWaitForMultipleObjects (
-	IN ULONG Count,
-	IN HANDLE Object[],
+	IN ULONG ObjectCount,
+	IN PHANDLE ObjectsArray,
 	IN WAIT_TYPE WaitType,
 	IN BOOLEAN Alertable,
-	IN PLARGE_INTEGER Time
+	IN PLARGE_INTEGER TimeOut  OPTIONAL
 	);
 
 
@@ -6357,11 +6357,11 @@
 /*
  * FUNCTION: Waits for multiple objects to become signalled.
  * ARGUMENTS: 
- *       Count = The number of objects
- *       Object = The array of object handles
+ *       ObjectCount = The number of objects
+ *       ObjectsArray = The array of object handles
  *       WaitType = Can be one of the values UserMode or KernelMode
  *       Alertable = If true the wait is alertable.
- *       Time = The maximum wait time.
+ *       TimeOut = The maximum wait time.
  * REMARKS:
  *       This function maps to the win32 WaitForMultipleObjectEx.
  * RETURNS: Status
@@ -6369,11 +6369,11 @@
 NTSTATUS
 STDCALL
 ZwWaitForMultipleObjects (
-	IN ULONG Count,
-	IN HANDLE Object[],
+	IN ULONG ObjectCount,
+	IN PHANDLE ObjectsArray,
 	IN WAIT_TYPE WaitType,
 	IN BOOLEAN Alertable,
-	IN PLARGE_INTEGER Time
+	IN PLARGE_INTEGER TimeOut  OPTIONAL
 	);
 
 /*

Modified: trunk/reactos/ntoskrnl/ke/wait.c
--- trunk/reactos/ntoskrnl/ke/wait.c	2005-02-14 21:41:49 UTC (rev 13578)
+++ trunk/reactos/ntoskrnl/ke/wait.c	2005-02-14 22:50:15 UTC (rev 13579)
@@ -785,45 +785,71 @@
 }
 
 NTSTATUS STDCALL
-NtWaitForMultipleObjects(IN ULONG Count,
-			 IN HANDLE Object [],
+NtWaitForMultipleObjects(IN ULONG ObjectCount,
+			 IN PHANDLE ObjectsArray,
 			 IN WAIT_TYPE WaitType,
 			 IN BOOLEAN Alertable,
-			 IN PLARGE_INTEGER UnsafeTime)
+			 IN PLARGE_INTEGER TimeOut  OPTIONAL)
 {
    KWAIT_BLOCK WaitBlockArray[MAXIMUM_WAIT_OBJECTS];
+   HANDLE SafeObjectsArray[MAXIMUM_WAIT_OBJECTS];
    PVOID ObjectPtrArray[MAXIMUM_WAIT_OBJECTS];
-   NTSTATUS Status;
    ULONG i, j;
-   KPROCESSOR_MODE WaitMode;
-   LARGE_INTEGER Time;
+   KPROCESSOR_MODE PreviousMode;
+   LARGE_INTEGER SafeTimeOut;
+   NTSTATUS Status = STATUS_SUCCESS;
 
-   DPRINT("NtWaitForMultipleObjects(Count %lu Object[] %x, Alertable %d, "
-	  "Time %x)\n", Count,Object,Alertable,Time);
+   DPRINT("NtWaitForMultipleObjects(ObjectCount %lu ObjectsArray[] %x, Alertable %d, "
+	  "TimeOut %x)\n", ObjectCount,ObjectsArray,Alertable,TimeOut);
 
-   if (Count > MAXIMUM_WAIT_OBJECTS)
+   PreviousMode = ExGetPreviousMode();
+
+   if (ObjectCount > MAXIMUM_WAIT_OBJECTS)
      return STATUS_UNSUCCESSFUL;
-   if (0 == Count)
+   if (0 == ObjectCount)
      return STATUS_INVALID_PARAMETER;
 
-   if (UnsafeTime)
+   if(PreviousMode != KernelMode)
+   {
+     _SEH_TRY
      {
-       Status = MmCopyFromCaller(&Time, UnsafeTime, sizeof(LARGE_INTEGER));
-       if (!NT_SUCCESS(Status))
-         {
-           return(Status);
-         }
+       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;
+     }
+   }
 
-   WaitMode = ExGetPreviousMode();
-
    /* reference all objects */
-   for (i = 0; i < Count; i++)
+   for (i = 0; i < ObjectCount; i++)
      {
-        Status = ObReferenceObjectByHandle(Object[i],
+        Status = ObReferenceObjectByHandle(ObjectsArray[i],
                                            SYNCHRONIZE,
                                            NULL,
-                                           WaitMode,
+                                           PreviousMode,
                                            &ObjectPtrArray[i],
                                            NULL);
         if (!NT_SUCCESS(Status) || !KiIsObjectWaitable(ObjectPtrArray[i]))
@@ -845,17 +871,17 @@
           }
      }
 
-   Status = KeWaitForMultipleObjects(Count,
+   Status = KeWaitForMultipleObjects(ObjectCount,
                                      ObjectPtrArray,
                                      WaitType,
                                      UserRequest,
-                                     WaitMode,
+                                     PreviousMode,
                                      Alertable,
-				     UnsafeTime ? &Time : NULL,
+				     TimeOut,
                                      WaitBlockArray);
 
    /* dereference all objects */
-   for (i = 0; i < Count; i++)
+   for (i = 0; i < ObjectCount; i++)
      {
         ObDereferenceObject(ObjectPtrArray[i]);
      }
@@ -868,33 +894,47 @@
  * @implemented
  */
 NTSTATUS STDCALL
-NtWaitForSingleObject(IN HANDLE Object,
+NtWaitForSingleObject(IN HANDLE ObjectHandle,
 		      IN BOOLEAN Alertable,
-		      IN PLARGE_INTEGER UnsafeTime)
+		      IN PLARGE_INTEGER TimeOut  OPTIONAL)
 {
    PVOID ObjectPtr;
-   NTSTATUS Status;
-   KPROCESSOR_MODE WaitMode;
-   LARGE_INTEGER Time;
+   KPROCESSOR_MODE PreviousMode;
+   LARGE_INTEGER SafeTimeOut;
+   NTSTATUS Status = STATUS_SUCCESS;
 
-   DPRINT("NtWaitForSingleObject(Object %x, Alertable %d, Time %x)\n",
-	  Object,Alertable,Time);
+   DPRINT("NtWaitForSingleObject(ObjectHandle %x, Alertable %d, TimeOut %x)\n",
+	  ObjectHandle,Alertable,TimeOut);
 
-   if (UnsafeTime)
+   PreviousMode = ExGetPreviousMode();
+   
+   if(TimeOut != NULL && PreviousMode != KernelMode)
+   {
+     _SEH_TRY
      {
-       Status = MmCopyFromCaller(&Time, UnsafeTime, sizeof(LARGE_INTEGER));
-       if (!NT_SUCCESS(Status))
-         {
-           return(Status);
-         }
+       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;
+     }
+   }
 
-   WaitMode = ExGetPreviousMode();
-
-   Status = ObReferenceObjectByHandle(Object,
+   Status = ObReferenceObjectByHandle(ObjectHandle,
 				      SYNCHRONIZE,
 				      NULL,
-				      WaitMode,
+				      PreviousMode,
 				      &ObjectPtr,
 				      NULL);
    if (!NT_SUCCESS(Status))
@@ -911,9 +951,9 @@
      {
        Status = KeWaitForSingleObject(ObjectPtr,
 				      UserRequest,
-				      WaitMode,
+				      PreviousMode,
 				      Alertable,
-				      UnsafeTime ? &Time : NULL);
+				      TimeOut);
      }
 
    ObDereferenceObject(ObjectPtr);
@@ -923,22 +963,47 @@
 
 
 NTSTATUS STDCALL
-NtSignalAndWaitForSingleObject(IN HANDLE SignalObject,
-			       IN HANDLE WaitObject,
+NtSignalAndWaitForSingleObject(IN HANDLE ObjectHandleToSignal,
+			       IN HANDLE WaitableObjectHandle,
 			       IN BOOLEAN Alertable,
-			       IN PLARGE_INTEGER Time)
+			       IN PLARGE_INTEGER TimeOut  OPTIONAL)
 {
-   KPROCESSOR_MODE WaitMode;
+   KPROCESSOR_MODE PreviousMode;
    DISPATCHER_HEADER* hdr;
    PVOID SignalObj;
    PVOID WaitObj;
-   NTSTATUS Status;
+   LARGE_INTEGER SafeTimeOut;
+   NTSTATUS Status = STATUS_SUCCESS;
 
-   WaitMode = ExGetPreviousMode();
-   Status = ObReferenceObjectByHandle(SignalObject,
+   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,
-				      WaitMode,
+				      PreviousMode,
 				      &SignalObj,
 				      NULL);
    if (!NT_SUCCESS(Status))
@@ -946,10 +1011,10 @@
 	return Status;
      }
 
-   Status = ObReferenceObjectByHandle(WaitObject,
+   Status = ObReferenceObjectByHandle(WaitableObjectHandle,
 				      SYNCHRONIZE,
 				      NULL,
-				      WaitMode,
+				      PreviousMode,
 				      &WaitObj,
 				      NULL);
    if (!NT_SUCCESS(Status))
@@ -988,9 +1053,9 @@
 
    Status = KeWaitForSingleObject(WaitObj,
 				  UserRequest,
-				  WaitMode,
+				  PreviousMode,
 				  Alertable,
-				  Time);
+				  TimeOut);
 
    ObDereferenceObject(SignalObj);
    ObDereferenceObject(WaitObj);

Modified: trunk/reactos/w32api/include/ddk/winddk.h
--- trunk/reactos/w32api/include/ddk/winddk.h	2005-02-14 21:41:49 UTC (rev 13578)
+++ trunk/reactos/w32api/include/ddk/winddk.h	2005-02-14 22:50:15 UTC (rev 13579)
@@ -9131,17 +9131,17 @@
 NTSTATUS
 DDKAPI
 NtWaitForSingleObject(
-  IN HANDLE  Object,
+  IN HANDLE  ObjectHandle,
   IN BOOLEAN  Alertable,
-  IN PLARGE_INTEGER  Time);
+  IN PLARGE_INTEGER  TimeOut  OPTIONAL);
 
 NTOSAPI
 NTSTATUS
 DDKAPI
 ZwWaitForSingleObject(
-  IN HANDLE  Object,
+  IN HANDLE  ObjectHandle,
   IN BOOLEAN  Alertable,
-  IN PLARGE_INTEGER  Time);
+  IN PLARGE_INTEGER  TimeOut  OPTIONAL);
 
 NTOSAPI
 NTSTATUS