Minor changes for NT compatibility.
[reactos.git] / reactos / ntoskrnl / lpc / send.c
index dab467b..6bd3f26 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: send.c,v 1.5 2001/06/23 19:13:33 phreak Exp $
+/* $Id: send.c,v 1.14 2004/01/07 21:13:22 ea Exp $
  * 
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
@@ -15,6 +15,7 @@
 #include <internal/ob.h>
 #include <internal/port.h>
 #include <internal/dbg.h>
+#include <internal/safe.h>
 
 #define NDEBUG
 #include <internal/debug.h>
@@ -22,6 +23,7 @@
 
 /**********************************************************************
  * NAME
+ *     LpcSendTerminationPort/2
  *
  * DESCRIPTION
  *
@@ -30,7 +32,6 @@
  * RETURN VALUE
  *
  * REVISIONS
- *
  */
 NTSTATUS STDCALL 
 LpcSendTerminationPort (IN PEPORT Port,
@@ -38,7 +39,10 @@ LpcSendTerminationPort (IN PEPORT Port,
 {
   NTSTATUS Status;
   LPC_TERMINATION_MESSAGE Msg;
-   
+  
+#ifdef __USE_NT_LPC__
+  Msg.Header.MessageType = LPC_NEW_MESSAGE;
+#endif
   Msg.CreationTime = CreationTime;
   Status = LpcRequestPort (Port, &Msg.Header);
   return(Status);
@@ -47,6 +51,7 @@ LpcSendTerminationPort (IN PEPORT Port,
 
 /**********************************************************************
  * NAME
+ *     LpcSendDebugMessagePort/3
  *
  * DESCRIPTION
  *
@@ -55,7 +60,6 @@ LpcSendTerminationPort (IN PEPORT Port,
  * RETURN VALUE
  *
  * REVISIONS
- *
  */
 NTSTATUS STDCALL 
 LpcSendDebugMessagePort (IN PEPORT Port,
@@ -75,8 +79,8 @@ LpcSendDebugMessagePort (IN PEPORT Port,
        ObDereferenceObject(Port);
        return(Status);
      }
-   KeReleaseSemaphore( &Port->OtherPort->Semaphore, IO_NO_INCREMENT, 1, FALSE );   
-   
+   KeReleaseSemaphore(&Port->OtherPort->Semaphore, IO_NO_INCREMENT, 1, FALSE);
+
    /*
     * Wait for a reply
     */
@@ -101,7 +105,8 @@ LpcSendDebugMessagePort (IN PEPORT Port,
 
 /**********************************************************************
  * NAME
- *
+ *     LpcRequestPort/2
+ *     
  * DESCRIPTION
  *
  * ARGUMENTS
@@ -109,15 +114,42 @@ LpcSendDebugMessagePort (IN PEPORT Port,
  * RETURN VALUE
  *
  * REVISIONS
+ *     2002-03-01 EA
+ *     I investigated this function a bit more in depth.
+ *     It looks like the legal values for the MessageType field in the 
+ *     message to send are in the range LPC_NEW_MESSAGE .. LPC_CLIENT_DIED,
+ *     but LPC_DATAGRAM is explicitly forbidden.
  *
+ * @implemented
  */
 NTSTATUS STDCALL LpcRequestPort (IN    PEPORT          Port,
                                 IN     PLPC_MESSAGE    LpcMessage)
 {
    NTSTATUS Status;
    
-   DPRINT("LpcRequestPort(PortHandle %x LpcMessage %x)\n", Port, LpcMessage);
-   
+   DPRINT("LpcRequestPort(PortHandle %08x, LpcMessage %08x)\n", Port, LpcMessage);
+
+#ifdef __USE_NT_LPC__
+   /* Check the message's type */
+   if (LPC_NEW_MESSAGE == LpcMessage->MessageType)
+   {
+      LpcMessage->MessageType = LPC_DATAGRAM;
+   }
+   else if (LPC_DATAGRAM == LpcMessage->MessageType)
+   {
+      return STATUS_INVALID_PARAMETER;
+   }
+   else if (LpcMessage->MessageType > LPC_CLIENT_DIED)
+   {
+      return STATUS_INVALID_PARAMETER;
+   }
+   /* Check the range offset */
+   if (0 != LpcMessage->VirtualRangesOffset)
+   {
+      return STATUS_INVALID_PARAMETER;
+   }
+#endif
+
    Status = EiReplyOrRequestPort(Port, 
                                 LpcMessage, 
                                 LPC_DATAGRAM,
@@ -130,6 +162,7 @@ NTSTATUS STDCALL LpcRequestPort (IN PEPORT          Port,
 
 /**********************************************************************
  * NAME
+ *     NtRequestPort/2
  *
  * DESCRIPTION
  *
@@ -139,6 +172,7 @@ NTSTATUS STDCALL LpcRequestPort (IN PEPORT          Port,
  *
  * REVISIONS
  *
+ * @implemented
  */
 NTSTATUS STDCALL NtRequestPort (IN     HANDLE          PortHandle,
                                IN      PLPC_MESSAGE    LpcMessage)
@@ -171,6 +205,7 @@ NTSTATUS STDCALL NtRequestPort (IN  HANDLE          PortHandle,
 
 /**********************************************************************
  * NAME
+ *     NtRequestWaitReplyPort/3
  *
  * DESCRIPTION
  *
@@ -180,20 +215,23 @@ NTSTATUS STDCALL NtRequestPort (IN        HANDLE          PortHandle,
  *
  * REVISIONS
  *
+ * @implemented
  */
 NTSTATUS STDCALL 
 NtRequestWaitReplyPort (IN HANDLE PortHandle,
-                       PLPC_MESSAGE LpcRequest,    
-                       PLPC_MESSAGE LpcReply)
+                       PLPC_MESSAGE UnsafeLpcRequest,    
+                       PLPC_MESSAGE UnsafeLpcReply)
 {
    NTSTATUS Status;
    PEPORT Port;
    PQUEUEDMESSAGE Message;
    KIRQL oldIrql;
-   
+   PLPC_MESSAGE LpcRequest;
+   USHORT LpcRequestMessageSize;
+
    DPRINT("NtRequestWaitReplyPort(PortHandle %x, LpcRequest %x, "
-         "LpcReply %x)\n", PortHandle, LpcRequest, LpcReply);
-   
+         "LpcReply %x)\n", PortHandle, UnsafeLpcRequest, UnsafeLpcReply);
+
    Status = ObReferenceObjectByHandle(PortHandle,
                                      PORT_ALL_ACCESS, 
                                      ExPortType,
@@ -204,8 +242,48 @@ NtRequestWaitReplyPort (IN HANDLE PortHandle,
      {
        return(Status);
      }
-   
-   
+
+   Status = MmCopyFromCaller(&LpcRequestMessageSize,
+                            &UnsafeLpcRequest->MessageSize,
+                            sizeof(USHORT));
+   if (!NT_SUCCESS(Status))
+     {
+       ObDereferenceObject(Port);
+       return(Status);
+     }
+   if (LpcRequestMessageSize > (sizeof(LPC_MESSAGE) + MAX_MESSAGE_DATA))
+     {
+       ObDereferenceObject(Port);
+       return(STATUS_PORT_MESSAGE_TOO_LONG);
+     }
+   LpcRequest = ExAllocatePool(NonPagedPool, LpcRequestMessageSize);
+   if (LpcRequest == NULL)
+     {
+       ObDereferenceObject(Port);
+       return(STATUS_NO_MEMORY);
+     }
+   Status = MmCopyFromCaller(LpcRequest, UnsafeLpcRequest,
+                            LpcRequestMessageSize);
+   if (!NT_SUCCESS(Status))
+     {
+       ExFreePool(LpcRequest);
+       ObDereferenceObject(Port);
+       return(Status);
+     }
+   LpcRequestMessageSize = LpcRequest->MessageSize;
+   if (LpcRequestMessageSize > (sizeof(LPC_MESSAGE) + MAX_MESSAGE_DATA))
+     {
+       ExFreePool(LpcRequest);
+       ObDereferenceObject(Port);
+       return(STATUS_PORT_MESSAGE_TOO_LONG);
+     }
+   if (LpcRequest->DataSize != (LpcRequest->MessageSize - sizeof(LPC_MESSAGE)))
+     {
+       ExFreePool(LpcRequest);
+       ObDereferenceObject(Port);
+       return(STATUS_PORT_MESSAGE_TOO_LONG);
+     }
+
    Status = EiReplyOrRequestPort(Port->OtherPort, 
                                 LpcRequest, 
                                 LPC_REQUEST,
@@ -213,40 +291,59 @@ NtRequestWaitReplyPort (IN HANDLE PortHandle,
    if (!NT_SUCCESS(Status))
      {
        DbgPrint("Enqueue failed\n");
+       ExFreePool(LpcRequest);
        ObDereferenceObject(Port);
        return(Status);
      }
-   KeReleaseSemaphore( &Port->OtherPort->Semaphore, IO_NO_INCREMENT, 1, FALSE);   
+   ExFreePool(LpcRequest);
+   KeReleaseSemaphore (&Port->OtherPort->Semaphore, IO_NO_INCREMENT, 
+                      1, FALSE);   
    
    /*
     * Wait for a reply
     */
-   KeWaitForSingleObject(&Port->Semaphore,
-                        UserRequest,
-                        UserMode,
-                        FALSE,
-                        NULL);
-   
-   /*
-    * Dequeue the reply
-    */
-   KeAcquireSpinLock(&Port->Lock, &oldIrql);
-   Message = EiDequeueMessagePort(Port);
-   KeReleaseSpinLock(&Port->Lock, oldIrql);
-   DPRINT("Message->Message.MessageSize %d\n",
-          Message->Message.MessageSize);
-   memcpy(LpcReply, &Message->Message, Message->Message.MessageSize);
-   ExFreePool(Message);
+   Status = KeWaitForSingleObject(&Port->Semaphore,
+                                 UserRequest,
+                                 UserMode,
+                                 FALSE,
+                                 NULL);
+   if (Status == STATUS_SUCCESS)
+     {
    
+       /*
+        * Dequeue the reply
+        */
+       KeAcquireSpinLock(&Port->Lock, &oldIrql);
+       Message = EiDequeueMessagePort(Port);
+       KeReleaseSpinLock(&Port->Lock, oldIrql);
+       if (Message)
+         {
+           DPRINT("Message->Message.MessageSize %d\n",
+                 Message->Message.MessageSize);
+           Status = MmCopyToCaller(UnsafeLpcReply, &Message->Message, 
+                                  Message->Message.MessageSize);
+           ExFreePool(Message);
+         }
+       else
+         Status = STATUS_UNSUCCESSFUL;
+     }
+   else
+     {
+       if (NT_SUCCESS(Status))
+         {
+          Status = STATUS_UNSUCCESSFUL;
+        }
+     }
    ObDereferenceObject(Port);
    
-   return(STATUS_SUCCESS);
+   return(Status);
 }
 
 
 /**********************************************************************
  * NAME
- *
+ *     NtWriteRequestData/6
+ *     
  * DESCRIPTION
  *
  * ARGUMENTS
@@ -254,7 +351,6 @@ NtRequestWaitReplyPort (IN HANDLE PortHandle,
  * RETURN VALUE
  *
  * REVISIONS
- *
  */
 NTSTATUS STDCALL NtWriteRequestData (HANDLE            PortHandle,
                                     PLPC_MESSAGE       Message,
@@ -264,6 +360,7 @@ NTSTATUS STDCALL NtWriteRequestData (HANDLE         PortHandle,
                                     PULONG             ReturnLength)
 {
    UNIMPLEMENTED;
+   return(STATUS_NOT_IMPLEMENTED);
 }