- Commit NTLPC and remove old implementation.
authorAlex Ionescu <aionescu@gmail.com>
Wed, 10 Jan 2007 04:27:40 +0000 (04:27 +0000)
committerAlex Ionescu <aionescu@gmail.com>
Wed, 10 Jan 2007 04:27:40 +0000 (04:27 +0000)
- Yeah, this adds another regression on top of the new Ob stuff, but in the end it's for the better, as it removes more race conditions and buggy code.
- This whole week I've fixed about 45 bugs and removed a dozen race conditions, sorry for the 2-3 regressions, they will be fixed ASAP.
- DELETE MAKEFILE.AUTO BEFORE BUILDING THIS BUILD.

svn path=/trunk/; revision=25411

25 files changed:
reactos/config.template.rbuild
reactos/ntoskrnl/include/internal/lpc.h
reactos/ntoskrnl/include/internal/lpc_x.h [moved from reactos/ntoskrnl/lpc/ntlpc/lpc_x.h with 97% similarity]
reactos/ntoskrnl/lpc/close.c
reactos/ntoskrnl/lpc/complete.c
reactos/ntoskrnl/lpc/connect.c
reactos/ntoskrnl/lpc/create.c
reactos/ntoskrnl/lpc/listen.c
reactos/ntoskrnl/lpc/ntlpc/close.c [deleted file]
reactos/ntoskrnl/lpc/ntlpc/complete.c [deleted file]
reactos/ntoskrnl/lpc/ntlpc/connect.c [deleted file]
reactos/ntoskrnl/lpc/ntlpc/create.c [deleted file]
reactos/ntoskrnl/lpc/ntlpc/listen.c [deleted file]
reactos/ntoskrnl/lpc/ntlpc/lpc.h [deleted file]
reactos/ntoskrnl/lpc/ntlpc/port.c [deleted file]
reactos/ntoskrnl/lpc/ntlpc/reply.c [deleted file]
reactos/ntoskrnl/lpc/ntlpc/send.c [deleted file]
reactos/ntoskrnl/lpc/port.c
reactos/ntoskrnl/lpc/query.c [deleted file]
reactos/ntoskrnl/lpc/queue.c [deleted file]
reactos/ntoskrnl/lpc/receive.c [deleted file]
reactos/ntoskrnl/lpc/reply.c
reactos/ntoskrnl/lpc/send.c
reactos/ntoskrnl/ntoskrnl.rbuild
reactos/ntoskrnl/ob/obhandle.c

index 92c8107..252e523 100644 (file)
@@ -75,6 +75,6 @@
   working on the \ntlpc directory. Leave this disabled unless you really know
   what you're doing.
 -->
-<property name="NTLPC" value="0" />
+<property name="NTLPC" value="1" />
 
 </rbuild>
index 8803f81..5570e81 100644 (file)
@@ -1,91 +1,56 @@
-#ifndef __INCLUDE_INTERNAL_PORT_H
-#define __INCLUDE_INTERNAL_PORT_H
-
-/* EPORT.Type */
-
-#define EPORT_TYPE_SERVER_RQST_PORT   (0)
-#define EPORT_TYPE_SERVER_COMM_PORT   (1)
-#define EPORT_TYPE_CLIENT_COMM_PORT   (2)
-
-/* EPORT.State */
-
-#define EPORT_INACTIVE                (0)
-#define EPORT_WAIT_FOR_CONNECT        (1)
-#define EPORT_WAIT_FOR_ACCEPT         (2)
-#define EPORT_WAIT_FOR_COMPLETE_SRV   (3)
-#define EPORT_WAIT_FOR_COMPLETE_CLT   (4)
-#define EPORT_CONNECTED_CLIENT        (5)
-#define EPORT_CONNECTED_SERVER        (6)
-#define EPORT_DISCONNECTED            (7)
-
-extern POBJECT_TYPE LpcPortObjectType;
-extern ULONG        LpcpNextMessageId;
-#ifndef NTLPC
-extern FAST_MUTEX   LpcpLock;
+/*
+* PROJECT:         ReactOS Kernel
+* LICENSE:         GPL - See COPYING in the top level directory
+* FILE:            ntoskrnl/include/lpc.h
+* PURPOSE:         Internal header for the Local Procedure Call
+* PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
+*/
+
+//
+// Define this if you want debugging support
+//
+#define _LPC_DEBUG_                                         0x01
+
+//
+// These define the Debug Masks Supported
+//
+#define LPC_CREATE_DEBUG                                    0x01
+#define LPC_CLOSE_DEBUG                                     0x02
+#define LPC_CONNECT_DEBUG                                   0x04
+#define LPC_LISTEN_DEBUG                                    0x08
+#define LPC_REPLY_DEBUG                                     0x10
+#define LPC_COMPLETE_DEBUG                                  0x20
+#define LPC_SEND_DEBUG                                      0x40
+
+//
+// Debug/Tracing support
+//
+#if _LPC_DEBUG_
+#ifdef NEW_DEBUG_SYSTEM_IMPLEMENTED // enable when Debug Filters are implemented
+#define LPCTRACE(x, ...)                                    \
+    {                                                       \
+        DbgPrintEx("%s [%.16s] - ",                         \
+                   __FUNCTION__,                            \
+                   PsGetCurrentProcess()->ImageFileName);   \
+        DbgPrintEx(__VA_ARGS__);                            \
+    }
+#else
+#define LPCTRACE(x, ...)                                    \
+    if (x & LpcpTraceLevel)                                 \
+    {                                                       \
+        DbgPrint("%s [%.16s:%lx] - ",                       \
+                 __FUNCTION__,                              \
+                 PsGetCurrentProcess()->ImageFileName,      \
+                 PsGetCurrentThreadId());                   \
+        DbgPrint(__VA_ARGS__);                              \
+    }
+#endif
 #endif
 
-typedef struct _EPORT_LISTENER
-{
-    HANDLE ListenerPid;
-    LIST_ENTRY ListenerListEntry;
-} EPORT_LISTENER, *PEPORT_LISTENER;
-
-typedef struct _EPORT
-{
-    KSPIN_LOCK Lock;
-    KSEMAPHORE Semaphore;
-    USHORT Type;
-    USHORT State;
-    struct _EPORT *RequestPort;
-    struct _EPORT *OtherPort;
-    ULONG QueueLength;
-    LIST_ENTRY QueueListHead;
-    ULONG ConnectQueueLength;
-    LIST_ENTRY ConnectQueueListHead;
-    ULONG MaxDataLength;
-    ULONG MaxConnectInfoLength;
-    ULONG MaxPoolUsage; /* size of NP zone */
-} EPORT, *PEPORT;
-
-typedef struct _EPORT_CONNECT_REQUEST_MESSAGE
-{
-    PORT_MESSAGE MessageHeader;
-    PEPROCESS ConnectingProcess;
-    struct _SECTION_OBJECT* SendSectionObject;
-    LARGE_INTEGER SendSectionOffset;
-    ULONG SendViewSize;
-    ULONG ConnectDataLength;
-    UCHAR ConnectData[0];
-} EPORT_CONNECT_REQUEST_MESSAGE, *PEPORT_CONNECT_REQUEST_MESSAGE;
-
-typedef struct _EPORT_CONNECT_REPLY_MESSAGE
-{
-    PORT_MESSAGE MessageHeader;
-    PVOID SendServerViewBase;
-    ULONG ReceiveClientViewSize;
-    PVOID ReceiveClientViewBase;
-    ULONG MaximumMessageSize;
-    ULONG ConnectDataLength;
-    UCHAR ConnectData[0];
-} EPORT_CONNECT_REPLY_MESSAGE, *PEPORT_CONNECT_REPLY_MESSAGE;
-
-typedef struct _QUEUEDMESSAGE
-{
-    PEPORT Sender;
-    LIST_ENTRY QueueListEntry;
-    PORT_MESSAGE Message;
-} QUEUEDMESSAGE, *PQUEUEDMESSAGE;
-
-NTSTATUS
-NTAPI
-LpcSendTerminationPort(
-    PEPORT Port,
-    LARGE_INTEGER CreationTime
-);
-
-/* Code in ntoskrnl/lpc/close.c */
-
-VOID 
+//
+// Internal Port Management
+//
+VOID
 NTAPI
 LpcpClosePort(
     IN PEPROCESS Process OPTIONAL,
@@ -97,66 +62,69 @@ LpcpClosePort(
 
 VOID
 NTAPI
-LpcpDeletePort(IN PVOID ObjectBody);
+LpcpDeletePort(
+    IN PVOID ObjectBody
+);
 
-VOID
+NTSTATUS
 NTAPI
-LpcExitThread(IN PETHREAD Thread);
-
-/* Code in ntoskrnl/lpc/queue.c */
+LpcpInitializePortQueue(
+    IN PLPCP_PORT_OBJECT Port
+);
 
 VOID
 NTAPI
-EiEnqueueConnectMessagePort(
-    IN OUT PEPORT Port,
-    IN PQUEUEDMESSAGE Message
+LpcpFreeToPortZone(
+    IN PLPCP_MESSAGE Message,
+    IN ULONG Flags
 );
 
 VOID
 NTAPI
-EiEnqueueMessagePort(
-    IN OUT PEPORT Port,
-    IN PQUEUEDMESSAGE Message
+LpcpMoveMessage(
+    IN PPORT_MESSAGE Destination,
+    IN PPORT_MESSAGE Origin,
+    IN PVOID Data,
+    IN ULONG MessageType,
+    IN PCLIENT_ID ClientId
 );
 
 VOID
 NTAPI
-EiEnqueueMessageAtHeadPort(
-    IN OUT PEPORT Port,
-    IN PQUEUEDMESSAGE Message
+LpcpSaveDataInfoMessage(
+    IN PLPCP_PORT_OBJECT Port,
+    IN PLPCP_MESSAGE Message
 );
 
-PQUEUEDMESSAGE
-NTAPI
-EiDequeueConnectMessagePort(IN OUT PEPORT Port);
-
-PQUEUEDMESSAGE
-NTAPI
-EiDequeueMessagePort(IN OUT PEPORT Port);
-
-/* Code in ntoskrnl/lpc/port.c */
-
-NTSTATUS
+//
+// Module-external utlity functions
+//
+VOID
 NTAPI
-LpcpInitializePort(
-    IN OUT PEPORT Port,
-    IN USHORT Type,
-    IN PEPORT Parent OPTIONAL
+LpcExitThread(
+    IN PETHREAD Thread
 );
 
+//
+// Initialization functions
+//
 NTSTATUS
 NTAPI
-LpcpInitSystem (VOID);
-
-/* Code in ntoskrnl/lpc/reply.c */
-
-NTSTATUS
-NTAPI
-EiReplyOrRequestPort(
-    IN PEPORT Port,
-    IN PPORT_MESSAGE LpcReply,
-    IN ULONG MessageType,
-    IN PEPORT Sender
+LpcpInitSystem(
+    VOID
 );
 
-#endif /* __INCLUDE_INTERNAL_PORT_H */
+//
+// Global data inside the Process Manager
+//
+extern POBJECT_TYPE LpcPortObjectType;
+extern ULONG LpcpNextMessageId, LpcpNextCallbackId;
+extern KGUARDED_MUTEX LpcpLock;
+extern PAGED_LOOKASIDE_LIST LpcpMessagesLookaside;
+extern ULONG LpcpMaxMessageSize;
+extern ULONG LpcpTraceLevel;
+
+//
+// Inlined Functions
+//
+#include "lpc_x.h"
similarity index 97%
rename from reactos/ntoskrnl/lpc/ntlpc/lpc_x.h
rename to reactos/ntoskrnl/include/internal/lpc_x.h
index 3c0bc8f..0ba3b0a 100644 (file)
-/*
-* PROJECT:         ReactOS Kernel
-* LICENSE:         GPL - See COPYING in the top level directory
-* FILE:            ntoskrnl/include/lpc_x.h
-* PURPOSE:         Intenral Inlined Functions for Local Procedure Call
-* PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
-*/
-
-//
-// Gets the message type, removing the kernel-mode flag
-//
-#define LpcpGetMessageType(x)                               \
-    ((x)->u2.s2.Type &~ LPC_KERNELMODE_MESSAGE)
-
-//
-// Waits on an LPC semaphore for a receive operation
-//
-#define LpcpReceiveWait(s, w)                               \
-{                                                           \
-    LPCTRACE(LPC_REPLY_DEBUG, "Wait: %p\n", s);             \
-    Status = KeWaitForSingleObject(s,                       \
-                                   WrLpcReceive,            \
-                                   w,                       \
-                                   FALSE,                   \
-                                   NULL);                   \
-    LPCTRACE(LPC_REPLY_DEBUG, "Wait done: %lx\n", Status);  \
-}
-
-//
-// Waits on an LPC semaphore for a reply operation
-//
-#define LpcpReplyWait(s, w)                                 \
-{                                                           \
-    LPCTRACE(LPC_SEND_DEBUG, "Wait: %p\n", s);              \
-    Status = KeWaitForSingleObject(s,                       \
-                                   WrLpcReply,              \
-                                   w,                       \
-                                   FALSE,                   \
-                                   NULL);                   \
-    LPCTRACE(LPC_SEND_DEBUG, "Wait done: %lx\n", Status);   \
-    if (Status == STATUS_USER_APC)                          \
-    {                                                       \
-        /* We were preempted by an APC */                   \
-        if (KeReadStateSemaphore(s))                        \
-        {                                                   \
-            /* It's still signaled, so wait on it */        \
-            KeWaitForSingleObject(s,                        \
-                                  Executive,                \
-                                  KernelMode,               \
-                                  FALSE,                    \
-                                  NULL);                    \
-            Status = STATUS_SUCCESS;                        \
-        }                                                   \
-    }                                                       \
-}
-
-//
-// Waits on an LPC semaphore for a connect operation
-//
-#define LpcpConnectWait(s, w)                               \
-{                                                           \
-    LPCTRACE(LPC_CONNECT_DEBUG, "Wait: %p\n", s);           \
-    Status = KeWaitForSingleObject(s,                       \
-                                   Executive,               \
-                                   w,                       \
-                                   FALSE,                   \
-                                   NULL);                   \
-    LPCTRACE(LPC_CONNECT_DEBUG, "Wait done: %lx\n", Status);\
-    if (Status == STATUS_USER_APC)                          \
-    {                                                       \
-        /* We were preempted by an APC */                   \
-        if (KeReadStateSemaphore(s))                        \
-        {                                                   \
-            /* It's still signaled, so wait on it */        \
-            KeWaitForSingleObject(s,                        \
-                                  Executive,                \
-                                  KernelMode,               \
-                                  FALSE,                    \
-                                  NULL);                    \
-            Status = STATUS_SUCCESS;                        \
-        }                                                   \
-    }                                                       \
-}
-
-//
-// Releases an LPC Semaphore to complete a wait
-//
-#define LpcpCompleteWait(s)                                 \
-{                                                           \
-    /* Release the semaphore */                             \
-    LPCTRACE(LPC_SEND_DEBUG, "Release: %p\n", s);           \
-    KeReleaseSemaphore(s, 1, 1, FALSE);                     \
-}
-
-//
-// Allocates a new message
-//
-PLPCP_MESSAGE
-FORCEINLINE
-LpcpAllocateFromPortZone(VOID)
-{
-    PLPCP_MESSAGE Message;
-
-    /* Allocate a message from the port zone while holding the lock */
-    KeAcquireGuardedMutex(&LpcpLock);
-    Message = ExAllocateFromPagedLookasideList(&LpcpMessagesLookaside);
-    if (!Message)
-    {
-        /* Fail, and let caller cleanup */
-        KeReleaseGuardedMutex(&LpcpLock);
-        return NULL;
-    }
-
-    /* Initialize it */
-    InitializeListHead(&Message->Entry);
-    Message->RepliedToThread = NULL;
-    Message->Request.u2.ZeroInit = 0;
-
-    /* Release the lock */
-    KeReleaseGuardedMutex(&LpcpLock);
-    return Message;
-}
+/*\r
+* PROJECT:         ReactOS Kernel\r
+* LICENSE:         GPL - See COPYING in the top level directory\r
+* FILE:            ntoskrnl/include/lpc_x.h\r
+* PURPOSE:         Intenral Inlined Functions for Local Procedure Call\r
+* PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)\r
+*/\r
+\r
+//\r
+// Gets the message type, removing the kernel-mode flag\r
+//\r
+#define LpcpGetMessageType(x)                               \\r
+    ((x)->u2.s2.Type &~ LPC_KERNELMODE_MESSAGE)\r
+\r
+//\r
+// Waits on an LPC semaphore for a receive operation\r
+//\r
+#define LpcpReceiveWait(s, w)                               \\r
+{                                                           \\r
+    LPCTRACE(LPC_REPLY_DEBUG, "Wait: %p\n", s);             \\r
+    Status = KeWaitForSingleObject(s,                       \\r
+                                   WrLpcReceive,            \\r
+                                   w,                       \\r
+                                   FALSE,                   \\r
+                                   NULL);                   \\r
+    LPCTRACE(LPC_REPLY_DEBUG, "Wait done: %lx\n", Status);  \\r
+}\r
+\r
+//\r
+// Waits on an LPC semaphore for a reply operation\r
+//\r
+#define LpcpReplyWait(s, w)                                 \\r
+{                                                           \\r
+    LPCTRACE(LPC_SEND_DEBUG, "Wait: %p\n", s);              \\r
+    Status = KeWaitForSingleObject(s,                       \\r
+                                   WrLpcReply,              \\r
+                                   w,                       \\r
+                                   FALSE,                   \\r
+                                   NULL);                   \\r
+    LPCTRACE(LPC_SEND_DEBUG, "Wait done: %lx\n", Status);   \\r
+    if (Status == STATUS_USER_APC)                          \\r
+    {                                                       \\r
+        /* We were preempted by an APC */                   \\r
+        if (KeReadStateSemaphore(s))                        \\r
+        {                                                   \\r
+            /* It's still signaled, so wait on it */        \\r
+            KeWaitForSingleObject(s,                        \\r
+                                  Executive,                \\r
+                                  KernelMode,               \\r
+                                  FALSE,                    \\r
+                                  NULL);                    \\r
+            Status = STATUS_SUCCESS;                        \\r
+        }                                                   \\r
+    }                                                       \\r
+}\r
+\r
+//\r
+// Waits on an LPC semaphore for a connect operation\r
+//\r
+#define LpcpConnectWait(s, w)                               \\r
+{                                                           \\r
+    LPCTRACE(LPC_CONNECT_DEBUG, "Wait: %p\n", s);           \\r
+    Status = KeWaitForSingleObject(s,                       \\r
+                                   Executive,               \\r
+                                   w,                       \\r
+                                   FALSE,                   \\r
+                                   NULL);                   \\r
+    LPCTRACE(LPC_CONNECT_DEBUG, "Wait done: %lx\n", Status);\\r
+    if (Status == STATUS_USER_APC)                          \\r
+    {                                                       \\r
+        /* We were preempted by an APC */                   \\r
+        if (KeReadStateSemaphore(s))                        \\r
+        {                                                   \\r
+            /* It's still signaled, so wait on it */        \\r
+            KeWaitForSingleObject(s,                        \\r
+                                  Executive,                \\r
+                                  KernelMode,               \\r
+                                  FALSE,                    \\r
+                                  NULL);                    \\r
+            Status = STATUS_SUCCESS;                        \\r
+        }                                                   \\r
+    }                                                       \\r
+}\r
+\r
+//\r
+// Releases an LPC Semaphore to complete a wait\r
+//\r
+#define LpcpCompleteWait(s)                                 \\r
+{                                                           \\r
+    /* Release the semaphore */                             \\r
+    LPCTRACE(LPC_SEND_DEBUG, "Release: %p\n", s);           \\r
+    KeReleaseSemaphore(s, 1, 1, FALSE);                     \\r
+}\r
+\r
+//\r
+// Allocates a new message\r
+//\r
+PLPCP_MESSAGE\r
+FORCEINLINE\r
+LpcpAllocateFromPortZone(VOID)\r
+{\r
+    PLPCP_MESSAGE Message;\r
+\r
+    /* Allocate a message from the port zone while holding the lock */\r
+    KeAcquireGuardedMutex(&LpcpLock);\r
+    Message = ExAllocateFromPagedLookasideList(&LpcpMessagesLookaside);\r
+    if (!Message)\r
+    {\r
+        /* Fail, and let caller cleanup */\r
+        KeReleaseGuardedMutex(&LpcpLock);\r
+        return NULL;\r
+    }\r
+\r
+    /* Initialize it */\r
+    InitializeListHead(&Message->Entry);\r
+    Message->RepliedToThread = NULL;\r
+    Message->Request.u2.ZeroInit = 0;\r
+\r
+    /* Release the lock */\r
+    KeReleaseGuardedMutex(&LpcpLock);\r
+    return Message;\r
+}\r
index cf569dc..af9803d 100644 (file)
@@ -1,25 +1,29 @@
-/* $Id$
- *
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS kernel
+/*
+ * PROJECT:         ReactOS Kernel
+ * LICENSE:         GPL - See COPYING in the top level directory
  * FILE:            ntoskrnl/lpc/close.c
- * PURPOSE:         Communication mechanism
- *
- * PROGRAMMERS:     David Welch (welch@cwcom.net)
+ * PURPOSE:         Local Procedure Call: Rundown, Cleanup, Deletion
+ * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
  */
 
-/* INCLUDES *****************************************************************/
+/* INCLUDES ******************************************************************/
 
 #include <ntoskrnl.h>
+#include "lpc.h"
 #define NDEBUG
 #include <internal/debug.h>
 
-/* FUNCTIONS *****************************************************************/
+/* PRIVATE FUNCTIONS *********************************************************/
 
 VOID
 NTAPI
 LpcExitThread(IN PETHREAD Thread)
 {
+    PLPCP_MESSAGE Message;
+
+    /* Acquire the lock */
+    KeAcquireGuardedMutex(&LpcpLock);
+
     /* Make sure that the Reply Chain is empty */
     if (!IsListEmpty(&Thread->LpcReplyChain))
     {
@@ -31,104 +35,361 @@ LpcExitThread(IN PETHREAD Thread)
     Thread->LpcExitThreadCalled = TRUE;
     Thread->LpcReplyMessageId = 0;
 
-    /* FIXME: Reply to the LpcReplyMessage */
+    /* Check if there's a reply message */
+    Message = Thread->LpcReplyMessage;
+    if (Message)
+    {
+        /* FIXME: TODO */
+        KEBUGCHECK(0);
+    }
+
+    /* Release the lock */
+    KeReleaseGuardedMutex(&LpcpLock);
 }
 
-/**********************************************************************
- * NAME
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- *
- * RETURN VALUE
- *
- * REVISIONS
- */
-VOID STDCALL
-LpcpClosePort (IN PEPROCESS Process OPTIONAL,
-               IN PVOID ObjectBody,
-               IN ACCESS_MASK GrantedAccess,
-               IN ULONG HandleCount,
-               IN ULONG SystemHandleCount)
+VOID
+NTAPI
+LpcpFreeToPortZone(IN PLPCP_MESSAGE Message,
+                   IN ULONG Flags)
 {
-  PEPORT Port = (PEPORT)ObjectBody;
-  PORT_MESSAGE Message;
+    PLPCP_CONNECTION_MESSAGE ConnectMessage;
+    PLPCP_PORT_OBJECT ClientPort = NULL;
+    PETHREAD Thread = NULL;
+    BOOLEAN LockHeld = Flags & 1;
+    PAGED_CODE();
+    LPCTRACE(LPC_CLOSE_DEBUG, "Message: %p. Flags: %lx\n", Message, Flags);
+
+    /* Acquire the lock if not already */
+    if (!LockHeld) KeAcquireGuardedMutex(&LpcpLock);
 
-  /* FIXME Race conditions here! */
+    /* Check if the queue list is empty */
+    if (!IsListEmpty(&Message->Entry))
+    {
+        /* Remove and re-initialize */
+        RemoveEntryList(&Message->Entry);
+        InitializeListHead(&Message->Entry);
+    }
 
-  /*
-   * If the client has just closed its handle then tell the server what
-   * happened and disconnect this port.
-   */
-  if (!(HandleCount)&& (Port->State == EPORT_CONNECTED_CLIENT))
+    /* Check if we've already replied */
+    if (Message->RepliedToThread)
     {
-      DPRINT("Informing server\n");
-      Message.u1.s1.TotalLength = sizeof(PORT_MESSAGE);
-      Message.u1.s1.DataLength = 0;
-      EiReplyOrRequestPort (Port->OtherPort,
-                           &Message,
-                           LPC_PORT_CLOSED,
-                           Port);
-      Port->OtherPort->OtherPort = NULL;
-      Port->OtherPort->State = EPORT_DISCONNECTED;
-      KeReleaseSemaphore( &Port->OtherPort->Semaphore,
-                         IO_NO_INCREMENT,
-                         1,
-                         FALSE );
-      ObDereferenceObject (Port);
+        /* Set thread to dereference and clean up */
+        Thread = Message->RepliedToThread;
+        Message->RepliedToThread = NULL;
     }
 
-  /*
-   * If the server has closed all of its handles then disconnect the port,
-   * don't actually notify the client until it attempts an operation.
-   */
-  if (!(HandleCount)&& (Port->State == EPORT_CONNECTED_SERVER))
+    /* Check if this is a connection request */
+    if (Message->Request.u2.s2.Type == LPC_CONNECTION_REQUEST)
     {
-        DPRINT("Cleaning up server\n");
-       Port->OtherPort->OtherPort = NULL;
-       Port->OtherPort->State = EPORT_DISCONNECTED;
-       ObDereferenceObject(Port->OtherPort);
-     }
+        /* Get the connection message */
+        ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(Message + 1);
+
+        /* Clear the client port */
+        ClientPort = ConnectMessage->ClientPort;
+        if (ClientPort) ConnectMessage->ClientPort = NULL;
+    }
+
+    /* Release the lock */
+    KeReleaseGuardedMutex(&LpcpLock);
+
+    /* Check if we had anything to dereference */
+    if (Thread) ObDereferenceObject(Thread);
+    if (ClientPort) ObDereferenceObject(ClientPort);
+
+    /* Free the entry */
+    ExFreeToPagedLookasideList(&LpcpMessagesLookaside, Message);
+
+    /* Reacquire the lock if needed */
+    if ((LockHeld) && !(Flags & 2)) KeAcquireGuardedMutex(&LpcpLock);
 }
 
+VOID
+NTAPI
+LpcpDestroyPortQueue(IN PLPCP_PORT_OBJECT Port,
+                     IN BOOLEAN Destroy)
+{
+    PLIST_ENTRY ListHead, NextEntry;
+    PETHREAD Thread;
+    PLPCP_MESSAGE Message;
+    PLPCP_CONNECTION_MESSAGE ConnectMessage;
+    LPCTRACE(LPC_CLOSE_DEBUG, "Port: %p. Flags: %lx\n", Port, Port->Flags);
+
+    /* Hold the lock */
+    KeAcquireGuardedMutex(&LpcpLock);
 
-/**********************************************************************
- * NAME
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- *
- * RETURN VALUE
- *
- * REVISIONS
- */
-VOID STDCALL
-LpcpDeletePort (PVOID  ObjectBody)
+    /* Disconnect the port to which this port is connected */
+    if (Port->ConnectedPort) Port->ConnectedPort->ConnectedPort = NULL;
+
+    /* Check if this is a connection port */
+    if ((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_CONNECTION_PORT)
+    {
+        /* Delete the name */
+        Port->Flags |= LPCP_NAME_DELETED;
+    }
+
+    /* Walk all the threads waiting and signal them */
+    ListHead = &Port->LpcReplyChainHead;
+    NextEntry = ListHead->Flink;
+    while (NextEntry != ListHead)
+    {
+        /* Get the Thread */
+        Thread = CONTAINING_RECORD(NextEntry, ETHREAD, LpcReplyChain);
+
+        /* Make sure we're not in exit */
+        if (Thread->LpcExitThreadCalled) break;
+
+        /* Move to the next entry */
+        NextEntry = NextEntry->Flink;
+
+        /* Remove and reinitialize the List */
+        RemoveEntryList(&Thread->LpcReplyChain);
+        InitializeListHead(&Thread->LpcReplyChain);
+
+        /* Check if someone is waiting */
+        if (!KeReadStateSemaphore(&Thread->LpcReplySemaphore))
+        {
+            /* Get the message and check if it's a connection request */
+            Message = Thread->LpcReplyMessage;
+            if (Message->Request.u2.s2.Type == LPC_CONNECTION_REQUEST)
+            {
+                /* Get the connection message */
+                ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(Message + 1);
+
+                /* Check if it had a section */
+                if (ConnectMessage->SectionToMap)
+                {
+                    /* Dereference it */
+                    ObDereferenceObject(ConnectMessage->SectionToMap);
+                }
+            }
+
+            /* Clear the reply message */
+            Thread->LpcReplyMessage = NULL;
+
+            /* And remove the message from the port zone */
+            LpcpFreeToPortZone(Message, TRUE);
+        }
+
+        /* Release the semaphore and reset message id count */
+        Thread->LpcReplyMessageId = 0;
+        LpcpCompleteWait(&Thread->LpcReplySemaphore);
+    }
+
+    /* Reinitialize the list head */
+    InitializeListHead(&Port->LpcReplyChainHead);
+
+    /* Loop queued messages */
+    ListHead = &Port->MsgQueue.ReceiveHead;
+    NextEntry =  ListHead->Flink;
+    while (ListHead != NextEntry)
+    {
+        /* Get the message */
+        Message = CONTAINING_RECORD(NextEntry, LPCP_MESSAGE, Entry);
+        NextEntry = NextEntry->Flink;
+
+        /* Free and reinitialize it's list head */
+        InitializeListHead(&Message->Entry);
+
+        /* Remove it from the port zone */
+        LpcpFreeToPortZone(Message, TRUE);
+    }
+
+    /* Reinitialize the message queue list head */
+    InitializeListHead(&Port->MsgQueue.ReceiveHead);
+
+    /* Release the lock */
+    KeReleaseGuardedMutex(&LpcpLock);
+
+    /* Check if we have to free the port entirely */
+    if (Destroy)
+    {
+        /* Check if the semaphore exists */
+        if (Port->MsgQueue.Semaphore)
+        {
+            /* Use the semaphore to find the port queue and free it */
+            ExFreePool(CONTAINING_RECORD(Port->MsgQueue.Semaphore,
+                                         LPCP_NONPAGED_PORT_QUEUE,
+                                         Semaphore));
+        }
+    }
+}
+
+VOID
+NTAPI
+LpcpClosePort(IN PEPROCESS Process OPTIONAL,
+              IN PVOID Object,
+              IN ACCESS_MASK GrantedAccess,
+              IN ULONG ProcessHandleCount,
+              IN ULONG SystemHandleCount)
+{
+    PLPCP_PORT_OBJECT Port = (PLPCP_PORT_OBJECT)Object;
+    LPCTRACE(LPC_CLOSE_DEBUG, "Port: %p. Flags: %lx\n", Port, Port->Flags);
+
+    /* Only Server-side Connection Ports need clean up*/
+    if ((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_CONNECTION_PORT)
+    {
+        /* Check the handle count */
+        switch (SystemHandleCount)
+        {
+            /* No handles left */
+            case 0:
+
+                /* Destroy the port queue */
+                LpcpDestroyPortQueue(Port, TRUE);
+                break;
+
+            /* Last handle remaining */
+            case 1:
+
+                /* Reset the queue only */
+                LpcpDestroyPortQueue(Port, FALSE);
+
+            /* More handles remain, do nothing */
+            default:
+                break;
+        }
+    }
+}
+
+VOID
+NTAPI
+LpcpFreePortClientSecurity(IN PLPCP_PORT_OBJECT Port)
 {
-   PLIST_ENTRY Entry;
-   PQUEUEDMESSAGE      Message;
-
-   PEPORT Port = (PEPORT)ObjectBody;
-
-   DPRINT("Deleting port %x\n", Port);
-
-   /* Free all waiting messages */
-   while (!IsListEmpty(&Port->QueueListHead))
-     {
-       Entry = RemoveHeadList(&Port->QueueListHead);
-       Message = CONTAINING_RECORD (Entry, QUEUEDMESSAGE, QueueListEntry);
-       ExFreePool(Message);
-     }
-
-   while (!IsListEmpty(&Port->ConnectQueueListHead))
-     {
-       Entry = RemoveHeadList(&Port->ConnectQueueListHead);
-       Message = CONTAINING_RECORD (Entry, QUEUEDMESSAGE, QueueListEntry);
-       ExFreePool(Message);
-     }
+    /* Check if this is a client port */
+    if ((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_CLIENT_PORT)
+    {
+        /* Check if security is static */
+        if (!(Port->Flags & LPCP_SECURITY_DYNAMIC))
+        {
+            /* Check if we have a token */
+            if (Port->StaticSecurity.ClientToken)
+            {
+                /* Free security */
+                SeDeleteClientSecurity(&Port->StaticSecurity);
+            }
+        }
+    }
 }
 
+VOID
+NTAPI
+LpcpDeletePort(IN PVOID ObjectBody)
+{
+    LARGE_INTEGER Timeout;
+    PETHREAD Thread;
+    PLPCP_PORT_OBJECT Port = (PLPCP_PORT_OBJECT)ObjectBody;
+    PLPCP_PORT_OBJECT ConnectionPort;
+    PLPCP_MESSAGE Message;
+    PLIST_ENTRY ListHead, NextEntry;
+    HANDLE Pid;
+    CLIENT_DIED_MSG ClientDiedMsg;
+    Timeout.QuadPart = -1000000;
+    PAGED_CODE();
+    LPCTRACE(LPC_CLOSE_DEBUG, "Port: %p. Flags: %lx\n", Port, Port->Flags);
+
+    /* Check if this is a communication port */
+    if ((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_COMMUNICATION_PORT)
+    {
+        /* Acquire the lock */
+        KeAcquireGuardedMutex(&LpcpLock);
+
+        /* Get the thread */
+        Thread = Port->ClientThread;
+        if (Thread)
+        {
+            /* Clear it */
+            Port->ClientThread = NULL;
+
+            /* Release the lock and dereference */
+            KeReleaseGuardedMutex(&LpcpLock);
+            ObDereferenceObject(Thread);
+        }
+        else
+        {
+            /* Release the lock */
+            KeReleaseGuardedMutex(&LpcpLock);
+        }
+    }
+
+    /* Check if this is a client-side port */
+    if ((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_CLIENT_PORT)
+    {
+        /* Setup the client died message */
+        ClientDiedMsg.h.u1.s1.TotalLength = sizeof(ClientDiedMsg);
+        ClientDiedMsg.h.u1.s1.DataLength = sizeof(ClientDiedMsg.CreateTime);
+        ClientDiedMsg.h.u2.ZeroInit = LPC_PORT_CLOSED;
+        ClientDiedMsg.CreateTime = PsGetCurrentProcess()->CreateTime;
+
+        /* Send it */
+        for (;;)
+        {
+            /* Send the message */
+            if (LpcRequestPort(Port,
+                               &ClientDiedMsg.h) != STATUS_NO_MEMORY) break;
+
+            /* Wait until trying again */
+            KeDelayExecutionThread(KernelMode, FALSE, &Timeout);
+        }
+    }
+
+    /* Destroy the port queue */
+    LpcpDestroyPortQueue(Port, TRUE);
+
+    /* Check if we had a client view */
+    if (Port->ClientSectionBase) MmUnmapViewOfSection(PsGetCurrentProcess(),
+                                                      Port->ClientSectionBase);
+
+    /* Check for a server view */
+    if (Port->ServerSectionBase) MmUnmapViewOfSection(PsGetCurrentProcess(),
+                                                      Port->ServerSectionBase);
+
+    /* Get the connection port */
+    ConnectionPort = Port->ConnectionPort;
+    if (ConnectionPort)
+    {
+        /* Get the PID */
+        Pid = PsGetCurrentProcessId();
+
+        /* Acquire the lock */
+        KeAcquireGuardedMutex(&LpcpLock);
+
+        /* Loop the data lists */
+        ListHead = &ConnectionPort->LpcDataInfoChainHead;
+        NextEntry = ListHead->Flink;
+        while (NextEntry != ListHead)
+        {
+            /* Get the message */
+            Message = CONTAINING_RECORD(NextEntry, LPCP_MESSAGE, Entry);
+            NextEntry = NextEntry->Flink;
+
+            /* Check if the PID matches */
+            if (Message->Request.ClientId.UniqueProcess == Pid)
+            {
+                /* Remove it */
+                RemoveEntryList(&Message->Entry);
+                LpcpFreeToPortZone(Message, TRUE);
+            }
+        }
+
+        /* Release the lock */
+        KeReleaseGuardedMutex(&LpcpLock);
+
+        /* Dereference the object unless it's the same port */
+        if (ConnectionPort != Port) ObDereferenceObject(ConnectionPort);
+    }
+
+    /* Check if this is a connection port with a server process*/
+    if (((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_CONNECTION_PORT) &&
+        (ConnectionPort->ServerProcess))
+    {
+        /* Dereference the server process */
+        ObDereferenceObject(ConnectionPort->ServerProcess);
+        ConnectionPort->ServerProcess = NULL;
+    }
+
+    /* Free client security */
+    LpcpFreePortClientSecurity(Port);
+    LPCTRACE(LPC_CLOSE_DEBUG, "Port: %p deleted\n", Port);
+}
 
 /* EOF */
index e14350d..b5e4e19 100644 (file)
-/* $Id$
- *
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS kernel
- * FILE:            ntoskrnl/lpc/complete.c
- * PURPOSE:         Communication mechanism
- *
- * PROGRAMMERS:     David Welch (welch@cwcom.net)
- */
+/*
+* PROJECT:         ReactOS Kernel
+* LICENSE:         GPL - See COPYING in the top level directory
+* FILE:            ntoskrnl/lpc/complete.c
+* PURPOSE:         Local Procedure Call: Connection Completion
+* PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
+*/
 
 /* INCLUDES ******************************************************************/
 
 #include <ntoskrnl.h>
+#include "lpc.h"
 #define NDEBUG
 #include <internal/debug.h>
 
-/* FUNCTIONS *****************************************************************/
-
-/***********************************************************************
- * NAME                                                        EXPORTED
- *     NtCompleteConnectPort/1
- *
- * DESCRIPTION
- *     Wake up the client thread that issued the NtConnectPort call
- *     this server-side port was created for communicating with.
- *     To be used in LPC servers processes on reply ports only.
- *
- * ARGUMENTS
- *     hServerSideCommPort: a reply port handle returned by
- *     NtAcceptConnectPort.
- *
- * RETURN VALUE
- *     STATUS_SUCCESS or an error code from Ob.
+/* PRIVATE FUNCTIONS *********************************************************/
+
+VOID
+NTAPI
+LpcpPrepareToWakeClient(IN PETHREAD Thread)
+{
+    PAGED_CODE();
+
+    /* Make sure the thread isn't dying and it has a valid chain */
+    if (!(Thread->LpcExitThreadCalled) &&
+        !(IsListEmpty(&Thread->LpcReplyChain)))
+    {
+        /* Remove it from the list and reinitialize it */
+        RemoveEntryList(&Thread->LpcReplyChain);
+        InitializeListHead(&Thread->LpcReplyChain);
+    }
+}
+
+/* PUBLIC FUNCTIONS **********************************************************/
+
+/*
+ * @implemented
  */
-NTSTATUS STDCALL
-NtCompleteConnectPort (HANDLE hServerSideCommPort)
+NTSTATUS
+NTAPI
+NtAcceptConnectPort(OUT PHANDLE PortHandle,
+                    IN PVOID PortContext OPTIONAL,
+                    IN PPORT_MESSAGE ReplyMessage,
+                    IN BOOLEAN AcceptConnection,
+                    IN PPORT_VIEW ServerView,
+                    IN PREMOTE_PORT_VIEW ClientView)
 {
-  NTSTATUS     Status;
-  PEPORT       ReplyPort;
-
-  DPRINT("NtCompleteConnectPort(hServerSideCommPort %x)\n", hServerSideCommPort);
-
-  /*
-   * Ask Ob to translate the port handle to EPORT
-   */
-  Status = ObReferenceObjectByHandle (hServerSideCommPort,
-                                     PORT_ALL_ACCESS,
-                                     LpcPortObjectType,
-                                     UserMode,
-                                     (PVOID*)&ReplyPort,
-                                     NULL);
-  if (!NT_SUCCESS(Status))
+    PLPCP_PORT_OBJECT ConnectionPort, ServerPort, ClientPort;
+    PVOID ClientSectionToMap = NULL;
+    HANDLE Handle;
+    KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
+    NTSTATUS Status;
+    ULONG ConnectionInfoLength;
+    PLPCP_MESSAGE Message;
+    PLPCP_CONNECTION_MESSAGE ConnectMessage;
+    PEPROCESS ClientProcess;
+    PETHREAD ClientThread;
+    LARGE_INTEGER SectionOffset;
+    PAGED_CODE();
+    LPCTRACE(LPC_COMPLETE_DEBUG,
+             "Context: %p. Message: %p. Accept: %lx. Views: %p/%p\n",
+             PortContext,
+             ReplyMessage,
+             AcceptConnection,
+             ClientView,
+             ServerView);
+
+    /* Validate the size of the server view */
+    if ((ServerView) && (ServerView->Length != sizeof(PORT_VIEW)))
     {
-      return (Status);
+        /* Invalid size */
+        return STATUS_INVALID_PARAMETER;
     }
-  /*
-   * Verify EPORT type is a server-side reply port;
-   * otherwise tell the caller the port handle is not
-   * valid.
-   */
-  if (ReplyPort->Type != EPORT_TYPE_SERVER_COMM_PORT)
+
+    /* Validate the size of the client view */
+    if ((ClientView) && (ClientView->Length != sizeof(REMOTE_PORT_VIEW)))
+    {
+        /* Invalid size */
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Get the client process and thread */
+    Status = PsLookupProcessThreadByCid(&ReplyMessage->ClientId,
+                                        &ClientProcess,
+                                        &ClientThread);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    /* Acquire the LPC Lock */
+    KeAcquireGuardedMutex(&LpcpLock);
+
+    /* Make sure that the client wants a reply, and this is the right one */
+    if (!(ClientThread->LpcReplyMessage) ||
+        !(ReplyMessage->MessageId) ||
+        (ClientThread->LpcReplyMessageId != ReplyMessage->MessageId))
     {
-       ObDereferenceObject (ReplyPort);
-       return STATUS_INVALID_PORT_HANDLE;
+        /* Not the reply asked for, or no reply wanted, fail */
+        KeReleaseGuardedMutex(&LpcpLock);
+        ObDereferenceObject(ClientProcess);
+        ObDereferenceObject(ClientThread);
+        return STATUS_REPLY_MESSAGE_MISMATCH;
     }
 
-  ReplyPort->State = EPORT_CONNECTED_SERVER;
-  /*
-   * Wake up the client thread that issued NtConnectPort.
-   */
-  KeReleaseSemaphore(&ReplyPort->OtherPort->Semaphore, IO_NO_INCREMENT, 1,
-                    FALSE);
-  /*
-   * Tell Ob we are no more interested in ReplyPort
-   */
-  ObDereferenceObject (ReplyPort);
-
-  return (STATUS_SUCCESS);
+    /* Now get the message and connection message */
+    Message = ClientThread->LpcReplyMessage;
+    ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(Message + 1);
+
+    /* Get the client and connection port as well */
+    ClientPort = ConnectMessage->ClientPort;
+    ConnectionPort = ClientPort->ConnectionPort;
+
+    /* Make sure that the reply is being sent to the proper server process */
+    if (ConnectionPort->ServerProcess != PsGetCurrentProcess())
+    {
+        /* It's not, so fail */
+        KeReleaseGuardedMutex(&LpcpLock);
+        ObDereferenceObject(ClientProcess);
+        ObDereferenceObject(ClientThread);
+        return STATUS_REPLY_MESSAGE_MISMATCH;
+    }
+
+    /* At this point, don't let other accept attempts happen */
+    ClientThread->LpcReplyMessage = NULL;
+    ClientThread->LpcReplyMessageId = 0;
+
+    /* Clear the client port for now as well, then release the lock */
+    ConnectMessage->ClientPort = NULL;
+    KeReleaseGuardedMutex(&LpcpLock);
+
+    /* Get the connection information length */
+    ConnectionInfoLength = ReplyMessage->u1.s1.DataLength;
+    if (ConnectionInfoLength > ConnectionPort->MaxConnectionInfoLength)
+    {
+        /* Normalize it since it's too large */
+        ConnectionInfoLength = ConnectionPort->MaxConnectionInfoLength;
+    }
+
+    /* Set the sizes of our reply message */
+    Message->Request.u1.s1.DataLength = sizeof(LPCP_CONNECTION_MESSAGE) +
+                                    ConnectionInfoLength;
+    Message->Request.u1.s1.TotalLength = sizeof(LPCP_MESSAGE) +
+                                     Message->Request.u1.s1.DataLength;
+
+    /* Setup the reply message */
+    Message->Request.u2.s2.Type = LPC_REPLY;
+    Message->Request.u2.s2.DataInfoOffset = 0;
+    Message->Request.ClientId = ReplyMessage->ClientId;
+    Message->Request.MessageId = ReplyMessage->MessageId;
+    Message->Request.ClientViewSize = 0;
+    RtlMoveMemory(ConnectMessage + 1, ReplyMessage + 1, ConnectionInfoLength);
+
+    /* At this point, if the caller refused the connection, go to cleanup */
+    if (!AcceptConnection) goto Cleanup;
+
+    /* Otherwise, create the actual port */
+    Status = ObCreateObject(PreviousMode,
+                            LpcPortObjectType,
+                            NULL,
+                            PreviousMode,
+                            NULL,
+                            sizeof(LPCP_PORT_OBJECT),
+                            0,
+                            0,
+                            (PVOID*)&ServerPort);
+    if (!NT_SUCCESS(Status)) goto Cleanup;
+
+    /* Set it up */
+    RtlZeroMemory(ServerPort, sizeof(LPCP_PORT_OBJECT));
+    ServerPort->PortContext = PortContext;
+    ServerPort->Flags = LPCP_COMMUNICATION_PORT;
+    ServerPort->MaxMessageLength = ConnectionPort->MaxMessageLength;
+    InitializeListHead(&ServerPort->LpcReplyChainHead);
+    InitializeListHead(&ServerPort->LpcDataInfoChainHead);
+
+    /* Reference the connection port until we're fully setup */
+    ObReferenceObject(ConnectionPort);
+
+    /* Link the ports together */
+    ServerPort->ConnectionPort = ConnectionPort;
+    ServerPort->ConnectedPort = ClientPort;
+    ClientPort->ConnectedPort = ServerPort;
+
+    /* Also set the creator CID */
+    ServerPort->Creator = PsGetCurrentThread()->Cid;
+    ClientPort->Creator = Message->Request.ClientId;
+
+    /* Get the section associated and then clear it, while inside the lock */
+    KeAcquireGuardedMutex(&LpcpLock);
+    ClientSectionToMap = ConnectMessage->SectionToMap;
+    ConnectMessage->SectionToMap = NULL;
+    KeReleaseGuardedMutex(&LpcpLock);
+
+    /* Now check if there's a client section */
+    if (ClientSectionToMap)
+    {
+        /* Setup the offset */
+        SectionOffset.QuadPart = ConnectMessage->ClientView.SectionOffset;
+
+        /* Map the section */
+        Status = MmMapViewOfSection(ClientSectionToMap,
+                                    PsGetCurrentProcess(),
+                                    &ServerPort->ClientSectionBase,
+                                    0,
+                                    0,
+                                    &SectionOffset,
+                                    &ConnectMessage->ClientView.ViewSize,
+                                    ViewUnmap,
+                                    0,
+                                    PAGE_READWRITE);
+
+        /* Update the offset and check for mapping status */
+        ConnectMessage->ClientView.SectionOffset = SectionOffset.LowPart;
+        if (NT_SUCCESS(Status))
+        {
+            /* Set the view base */
+            ConnectMessage->ClientView.ViewRemoteBase = ServerPort->
+                                                        ClientSectionBase;
+        }
+        else
+        {
+            /* Otherwise, quit */
+            ObDereferenceObject(ServerPort);
+            goto Cleanup;
+        }
+    }
+
+    /* Check if there's a server section */
+    if (ServerView)
+    {
+        /* FIXME: TODO */
+        ASSERT(FALSE);
+    }
+
+    /* Reference the server port until it's fully inserted */
+    ObReferenceObject(ServerPort);
+
+    /* Insert the server port in the namespace */
+    Status = ObInsertObject(ServerPort,
+                            NULL,
+                            PORT_ALL_ACCESS,
+                            0,
+                            NULL,
+                            &Handle);
+    if (!NT_SUCCESS(Status))
+    {
+        /* We failed, remove the extra reference and cleanup */
+        ObDereferenceObject(ServerPort);
+        goto Cleanup;
+    }
+
+    /* Check if the caller gave a client view */
+    if (ClientView)
+    {
+        /* Fill it out */
+        ClientView->ViewBase = ConnectMessage->ClientView.ViewRemoteBase;
+        ClientView->ViewSize = ConnectMessage->ClientView.ViewSize;
+    }
+
+    /* Return the handle to user mode */
+    *PortHandle = Handle;
+    LPCTRACE(LPC_COMPLETE_DEBUG,
+             "Handle: %lx. Messages: %p/%p. Ports: %p/%p/%p\n",
+             Handle,
+             Message,
+             ConnectMessage,
+             ServerPort,
+             ClientPort,
+             ConnectionPort);
+
+    /* If there was no port context, use the handle by default */
+    if (!PortContext) ServerPort->PortContext = Handle;
+    ServerPort->ClientThread = ClientThread;
+
+    /* Set this message as the LPC Reply message while holding the lock */
+    KeAcquireGuardedMutex(&LpcpLock);
+    ClientThread->LpcReplyMessage = Message;
+    KeReleaseGuardedMutex(&LpcpLock);
+
+    /* Clear the thread pointer so it doesn't get cleaned later */
+    ClientThread = NULL;
+
+    /* Remove the extra reference we had added */
+    ObDereferenceObject(ServerPort);
+
+Cleanup:
+    /* If there was a section, dereference it */
+    if (ClientSectionToMap) ObDereferenceObject(ClientSectionToMap);
+
+    /* Check if we got here while still having a client thread */
+    if (ClientThread)
+    {
+        /* FIXME: Complex cleanup code */
+        ASSERT(FALSE);
+    }
+
+    /* Dereference the client port if we have one, and the process */
+    LPCTRACE(LPC_COMPLETE_DEBUG,
+             "Status: %lx. Thread: %p. Process: [%.16s]\n",
+             Status,
+             ClientThread,
+             ClientProcess->ImageFileName);
+    if (ClientPort) ObDereferenceObject(ClientPort);
+    ObDereferenceObject(ClientProcess);
+    return Status;
 }
 
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+NtCompleteConnectPort(IN HANDLE PortHandle)
+{
+    NTSTATUS Status;
+    PLPCP_PORT_OBJECT Port;
+    KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
+    PETHREAD Thread;
+    PAGED_CODE();
+    LPCTRACE(LPC_COMPLETE_DEBUG, "Handle: %lx\n", PortHandle);
+
+    /* Get the Port Object */
+    Status = ObReferenceObjectByHandle(PortHandle,
+                                       PORT_ALL_ACCESS,
+                                       LpcPortObjectType,
+                                       PreviousMode,
+                                       (PVOID*)&Port,
+                                       NULL);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    /* Make sure this is a connection port */
+    if ((Port->Flags & LPCP_PORT_TYPE_MASK) != LPCP_COMMUNICATION_PORT)
+    {
+        /* It isn't, fail */
+        ObDereferenceObject(Port);
+        return STATUS_INVALID_PORT_HANDLE;
+    }
+
+    /* Acquire the lock */
+    KeAcquireGuardedMutex(&LpcpLock);
+
+    /* Make sure we have a client thread */
+    if (!Port->ClientThread)
+    {
+        /* We don't, fail */
+        KeReleaseGuardedMutex(&LpcpLock);
+        ObDereferenceObject(Port);
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Get the thread */
+    Thread = Port->ClientThread;
+
+    /* Make sure it has a reply message */
+    if (!Thread->LpcReplyMessage)
+    {
+        /* It doesn't, fail */
+        KeReleaseGuardedMutex(&LpcpLock);
+        ObDereferenceObject(Port);
+        return STATUS_PORT_DISCONNECTED;
+    }
+
+    /* Clear the client thread and wake it up */
+    Port->ClientThread = NULL;
+    LpcpPrepareToWakeClient(Thread);
+
+    /* Release the lock and wait for an answer */
+    KeReleaseGuardedMutex(&LpcpLock);
+    LpcpCompleteWait(&Thread->LpcReplySemaphore);
+
+    /* Dereference the Thread and Port  and return */
+    ObDereferenceObject(Port);
+    ObDereferenceObject(Thread);
+    LPCTRACE(LPC_COMPLETE_DEBUG, "Port: %p. Thread: %p\n", Port, Thread);
+    return Status;
+}
 
 /* EOF */
index 6aa3690..2b9259e 100644 (file)
-/* $Id$
- *
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS kernel
+/*
+ * PROJECT:         ReactOS Kernel
+ * LICENSE:         GPL - See COPYING in the top level directory
  * FILE:            ntoskrnl/lpc/connect.c
- * PURPOSE:         Communication mechanism
- *
- * PROGRAMMERS:     David Welch (welch@cwcom.net)
+ * PURPOSE:         Local Procedure Call: Connection Management
+ * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
  */
 
-/* INCLUDES *****************************************************************/
+/* INCLUDES ******************************************************************/
 
 #include <ntoskrnl.h>
+#include "lpc.h"
 #define NDEBUG
 #include <internal/debug.h>
 
-/* FUNCTIONS *****************************************************************/
-
-/**********************************************************************
- * NAME                                                        EXPORTED
- *     EiConnectPort/12
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- *
- * RETURN VALUE
- */
-NTSTATUS STDCALL
-EiConnectPort(IN PEPORT* ConnectedPort,
-             IN PEPORT NamedPort,
-             IN PVOID Section,
-             IN LARGE_INTEGER SectionOffset,
-             IN ULONG ViewSize,
-             OUT PVOID* ClientSendViewBase,
-             OUT PVOID* ServerSendViewBase,
-             OUT PULONG ReceiveViewSize,
-             OUT PVOID* ReceiveViewBase,
-             OUT PULONG MaximumMessageSize,
-             IN OUT PVOID ConnectData,
-             IN OUT PULONG ConnectDataLength)
+/* PRIVATE FUNCTIONS *********************************************************/
+
+PVOID
+NTAPI
+LpcpFreeConMsg(IN OUT PLPCP_MESSAGE *Message,
+               IN OUT PLPCP_CONNECTION_MESSAGE *ConnectMessage,
+               IN PETHREAD CurrentThread)
 {
-  PEPORT_CONNECT_REQUEST_MESSAGE RequestMessage;
-  ULONG RequestConnectDataLength;
-  PEPORT OurPort;
-  PQUEUEDMESSAGE Reply;
-  PEPORT_CONNECT_REPLY_MESSAGE CReply;
-  NTSTATUS Status;
-  KIRQL oldIrql;
-
-  if (ConnectDataLength == NULL)
-    {
-      RequestConnectDataLength = 0;
-    }
-  else
-    {
-      RequestConnectDataLength = *ConnectDataLength;
-    }
+    PVOID SectionToMap;
 
-  /*
-   * Create a port to represent our side of the connection
-   */
-  Status = ObCreateObject (KernelMode,
-                          LpcPortObjectType,
-                          NULL,
-                          KernelMode,
-                          NULL,
-                          sizeof(EPORT),
-                          0,
-                          0,
-                          (PVOID*)&OurPort);
-  if (!NT_SUCCESS(Status))
-    {
-      return (Status);
-    }
-  LpcpInitializePort(OurPort, EPORT_TYPE_CLIENT_COMM_PORT, NamedPort);
-
-  /*
-   * Allocate a request message.
-   */
-  RequestMessage = ExAllocatePool(NonPagedPool,
-                                 sizeof(EPORT_CONNECT_REQUEST_MESSAGE) +
-                                 RequestConnectDataLength);
-  if (RequestMessage == NULL)
-    {
-      ObDereferenceObject(OurPort);
-      return(STATUS_NO_MEMORY);
-    }
+    /* Acquire the LPC lock */
+    KeAcquireGuardedMutex(&LpcpLock);
 
-  /*
-   * Initialize the request message.
-   */
-  RequestMessage->MessageHeader.u1.s1.DataLength =
-    sizeof(EPORT_CONNECT_REQUEST_MESSAGE) + RequestConnectDataLength -
-    sizeof(PORT_MESSAGE);
-  RequestMessage->MessageHeader.u1.s1.TotalLength =
-    sizeof(EPORT_CONNECT_REQUEST_MESSAGE) + RequestConnectDataLength;
-  DPRINT("RequestMessageSize %d\n",
-        RequestMessage->MessageHeader.u1.s1.TotalLength);
-  RequestMessage->MessageHeader.ClientViewSize = 0;
-  RequestMessage->ConnectingProcess = PsGetCurrentProcess();
-  ObReferenceObjectByPointer(RequestMessage->ConnectingProcess,
-                            PROCESS_VM_OPERATION,
-                            NULL,
-                            KernelMode);
-  RequestMessage->SendSectionObject = (struct _SECTION_OBJECT*)Section;
-  RequestMessage->SendSectionOffset = SectionOffset;
-  RequestMessage->SendViewSize = ViewSize;
-  RequestMessage->ConnectDataLength = RequestConnectDataLength;
-  if (RequestConnectDataLength > 0)
+    /* Check if the reply chain is not empty */
+    if (!IsListEmpty(&CurrentThread->LpcReplyChain))
     {
-      memcpy(RequestMessage->ConnectData, ConnectData,
-            RequestConnectDataLength);
+        /* Remove this entry and re-initialize it */
+        RemoveEntryList(&CurrentThread->LpcReplyChain);
+        InitializeListHead(&CurrentThread->LpcReplyChain);
     }
 
-  /*
-   * Queue the message to the named port
-   */
-  EiReplyOrRequestPort(NamedPort,
-                      &RequestMessage->MessageHeader,
-                      LPC_CONNECTION_REQUEST,
-                      OurPort);
-  KeReleaseSemaphore(&NamedPort->Semaphore, IO_NO_INCREMENT, 1, FALSE);
-  ExFreePool(RequestMessage);
-
-  /*
-   * Wait for them to accept our connection
-   */
-  KeWaitForSingleObject(&OurPort->Semaphore,
-                       UserRequest,
-                       UserMode,
-                       FALSE,
-                       NULL);
-
-  /*
-   * Dequeue the response
-   */
-  KeAcquireSpinLock (&OurPort->Lock, &oldIrql);
-  Reply = EiDequeueMessagePort (OurPort);
-  KeReleaseSpinLock (&OurPort->Lock, oldIrql);
-  CReply = (PEPORT_CONNECT_REPLY_MESSAGE)&Reply->Message;
-
-  /*
-   * Do some initial cleanup.
-   */
-  ObDereferenceObject(PsGetCurrentProcess());
-
-  /*
-   * Check for connection refusal.
-   */
-  if (CReply->MessageHeader.u2.s2.Type == LPC_CONNECTION_REFUSED)
+    /* Check if there's a reply message */
+    if (CurrentThread->LpcReplyMessage)
     {
-      ObDereferenceObject(OurPort);
-      ExFreePool(Reply);
-      /*
-       * FIXME: Check what NT does here. Giving the user data back on
-       * connect failure sounds reasonable; it probably wouldn't break
-       * anything anyway.
-       */
-      if (ConnectDataLength != NULL)
-       {
-         *ConnectDataLength = CReply->ConnectDataLength;
-         memcpy(ConnectData, CReply->ConnectData, CReply->ConnectDataLength);
-       }
-      return(STATUS_PORT_CONNECTION_REFUSED);
-    }
+        /* Get the message */
+        *Message = CurrentThread->LpcReplyMessage;
 
-  /*
-   * Otherwise we are connected. Copy data back to the client.
-   */
-  *ServerSendViewBase = CReply->SendServerViewBase;
-  *ReceiveViewSize = CReply->ReceiveClientViewSize;
-  *ReceiveViewBase = CReply->ReceiveClientViewBase;
-  *MaximumMessageSize = CReply->MaximumMessageSize;
-  if (ConnectDataLength != NULL)
-    {
-      *ConnectDataLength = CReply->ConnectDataLength;
-      memcpy(ConnectData, CReply->ConnectData, CReply->ConnectDataLength);
-    }
+        /* Clear message data */
+        CurrentThread->LpcReceivedMessageId = 0;
+        CurrentThread->LpcReplyMessage = NULL;
 
-  /*
-   * Create our view of the send section object.
-   */
-  if (Section != NULL)
+        /* Get the connection message and clear the section */
+        *ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(*Message + 1);
+        SectionToMap = (*ConnectMessage)->SectionToMap;
+        (*ConnectMessage)->SectionToMap = NULL;
+    }
+    else
     {
-      *ClientSendViewBase = 0;
-      Status = MmMapViewOfSection(Section,
-                                 PsGetCurrentProcess(),
-                                 ClientSendViewBase,
-                                 0,
-                                 ViewSize,
-                                 &SectionOffset,
-                                 &ViewSize,
-                                 ViewUnmap,
-                                 0 /* MEM_TOP_DOWN? */,
-                                 PAGE_READWRITE);
-      if (!NT_SUCCESS(Status))
-       {
-         /* FIXME: Cleanup here. */
-         return(Status);
-       }
+        /* No message to return */
+        *Message = NULL;
+        SectionToMap = NULL;
     }
 
-  /*
-   * Do the final initialization of our port.
-   */
-  OurPort->State = EPORT_CONNECTED_CLIENT;
-
-  /*
-   * Cleanup.
-   */
-  ExFreePool(Reply);
-  *ConnectedPort = OurPort;
-  return(STATUS_SUCCESS);
+    /* Release the lock and return the section */
+    KeReleaseGuardedMutex(&LpcpLock);
+    return SectionToMap;
 }
 
-/**********************************************************************
- * NAME                                                        EXPORTED
- *     NtConnectPort/8
- *
- * DESCRIPTION
- *     Connect to a named port and wait for the other side to
- *     accept or reject the connection request.
- *
- * ARGUMENTS
- *     ConnectedPort
- *     PortName
- *     Qos
- *     WriteMap
- *     ReadMap
- *     MaxMessageSize
- *     ConnectInfo
- *     UserConnectInfoLength
- *
- * RETURN VALUE
- *
- * @unimplemented
+/* PUBLIC FUNCTIONS **********************************************************/
+
+/*
+ * @implemented
  */
-NTSTATUS STDCALL
-NtConnectPort (PHANDLE                         UnsafeConnectedPortHandle,
-              PUNICODE_STRING                  PortName,
-              PSECURITY_QUALITY_OF_SERVICE     Qos,
-              PPORT_VIEW               UnsafeWriteMap,
-              PREMOTE_PORT_VIEW                UnsafeReadMap,
-              PULONG                           UnsafeMaximumMessageSize,
-              PVOID                            UnsafeConnectData,
-              PULONG                           UnsafeConnectDataLength)
+NTSTATUS
+NTAPI
+NtSecureConnectPort(OUT PHANDLE PortHandle,
+                    IN PUNICODE_STRING PortName,
+                    IN PSECURITY_QUALITY_OF_SERVICE Qos,
+                    IN OUT PPORT_VIEW ClientView OPTIONAL,
+                    IN PSID ServerSid OPTIONAL,
+                    IN OUT PREMOTE_PORT_VIEW ServerView OPTIONAL,
+                    OUT PULONG MaxMessageLength OPTIONAL,
+                    IN OUT PVOID ConnectionInformation OPTIONAL,
+                    IN OUT PULONG ConnectionInformationLength OPTIONAL)
 {
-  HANDLE ConnectedPortHandle;
-  PORT_VIEW WriteMap;
-  REMOTE_PORT_VIEW ReadMap;
-  ULONG MaximumMessageSize;
-  PVOID ConnectData = NULL;
-  ULONG ConnectDataLength = 0;
-  PVOID SectionObject;
-  LARGE_INTEGER SectionOffset;
-  PEPORT ConnectedPort;
-  KPROCESSOR_MODE PreviousMode;
-  NTSTATUS Status = STATUS_SUCCESS;
-  PEPORT NamedPort;
-  
-  PreviousMode = ExGetPreviousMode();
-  
-  if (PreviousMode != KernelMode)
-    {
-      _SEH_TRY
+    ULONG ConnectionInfoLength = 0;
+    PLPCP_PORT_OBJECT Port, ClientPort;
+    KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
+    NTSTATUS Status = STATUS_SUCCESS;
+    HANDLE Handle;
+    PVOID SectionToMap;
+    PLPCP_MESSAGE Message;
+    PLPCP_CONNECTION_MESSAGE ConnectMessage;
+    PETHREAD Thread = PsGetCurrentThread();
+    ULONG PortMessageLength;
+    LARGE_INTEGER SectionOffset;
+    PTOKEN Token;
+    PTOKEN_USER TokenUserInfo;
+    PAGED_CODE();
+    LPCTRACE(LPC_CONNECT_DEBUG,
+             "Name: %wZ. Qos: %p. Views: %p/%p. Sid: %p\n",
+             PortName,
+             Qos,
+             ClientView,
+             ServerView,
+             ServerSid);
+
+    /* Validate client view */
+    if ((ClientView) && (ClientView->Length != sizeof(PORT_VIEW)))
+    {
+        /* Fail */
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Validate server view */
+    if ((ServerView) && (ServerView->Length != sizeof(REMOTE_PORT_VIEW)))
+    {
+        /* Fail */
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Check if caller sent connection information length */
+    if (ConnectionInformationLength)
+    {
+        /* Retrieve the input length */
+        ConnectionInfoLength = *ConnectionInformationLength;
+    }
+
+    /* Get the port */
+    Status = ObReferenceObjectByName(PortName,
+                                     0,
+                                     NULL,
+                                     PORT_ALL_ACCESS,
+                                     LpcPortObjectType,
+                                     PreviousMode,
+                                     NULL,
+                                     (PVOID *)&Port);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    /* This has to be a connection port */
+    if ((Port->Flags & LPCP_PORT_TYPE_MASK) != LPCP_CONNECTION_PORT)
+    {
+        /* It isn't, so fail */
+        ObDereferenceObject(Port);
+        return STATUS_INVALID_PORT_HANDLE;
+    }
+
+    /* Check if we have a SID */
+    if (ServerSid)
+    {
+        /* Make sure that we have a server */
+        if (Port->ServerProcess)
         {
-          ProbeForWriteHandle(UnsafeConnectedPortHandle);
-          if (UnsafeMaximumMessageSize != NULL)
+            /* Get its token and query user information */
+            Token = PsReferencePrimaryToken(Port->ServerProcess);
+            //Status = SeQueryInformationToken(Token, TokenUser, (PVOID*)&TokenUserInfo);
+            // FIXME: Need SeQueryInformationToken
+            Status = STATUS_SUCCESS;
+            TokenUserInfo = ExAllocatePool(PagedPool, sizeof(TOKEN_USER));
+            TokenUserInfo->User.Sid = ServerSid;
+            PsDereferencePrimaryToken(Token);
+
+            /* Check for success */
+            if (NT_SUCCESS(Status))
             {
-              ProbeForWriteUlong(UnsafeMaximumMessageSize);
+                /* Compare the SIDs */
+                if (!RtlEqualSid(ServerSid, TokenUserInfo->User.Sid))
+                {
+                    /* Fail */
+                    Status = STATUS_SERVER_SID_MISMATCH;
+                }
+
+                /* Free token information */
+                ExFreePool(TokenUserInfo);
             }
         }
-      _SEH_HANDLE
+        else
         {
-          Status = _SEH_GetExceptionCode();
+            /* Invalid SID */
+            Status = STATUS_SERVER_SID_MISMATCH;
         }
-      _SEH_END;
-      
-      if (!NT_SUCCESS(Status))
+
+        /* Check if SID failed */
+        if (!NT_SUCCESS(Status))
         {
-          return Status;
+            /* Quit */
+            ObDereferenceObject(Port);
+            return Status;
         }
     }
 
-  /*
-   * Copy in write map and partially validate.
-   */
-  if (UnsafeWriteMap != NULL)
-    {
-      if (PreviousMode != KernelMode)
-        {
-          _SEH_TRY
-            {
-              ProbeForWrite(UnsafeWriteMap,
-                            sizeof(PORT_VIEW),
-                            1);
-              RtlCopyMemory(&WriteMap,
-                            UnsafeWriteMap,
-                            sizeof(PORT_VIEW));
-            }
-          _SEH_HANDLE
-            {
-              Status = _SEH_GetExceptionCode();
-            }
-          _SEH_END;
-
-          if (!NT_SUCCESS(Status))
-            {
-              return Status;
-            }
-        }
-      else
+    /* Create the client port */
+    Status = ObCreateObject(PreviousMode,
+                            LpcPortObjectType,
+                            NULL,
+                            PreviousMode,
+                            NULL,
+                            sizeof(LPCP_PORT_OBJECT),
+                            0,
+                            0,
+                            (PVOID *)&ClientPort);
+    if (!NT_SUCCESS(Status))
+    {
+        /* Failed, dereference the server port and return */
+        ObDereferenceObject(Port);
+        return Status;
+    }
+
+    /* Setup the client port */
+    RtlZeroMemory(ClientPort, sizeof(LPCP_PORT_OBJECT));
+    ClientPort->Flags = LPCP_CLIENT_PORT;
+    ClientPort->ConnectionPort = Port;
+    ClientPort->MaxMessageLength = Port->MaxMessageLength;
+    ClientPort->SecurityQos = *Qos;
+    InitializeListHead(&ClientPort->LpcReplyChainHead);
+    InitializeListHead(&ClientPort->LpcDataInfoChainHead);
+
+    /* Check if we have dynamic security */
+    if (Qos->ContextTrackingMode == SECURITY_DYNAMIC_TRACKING)
+    {
+        /* Remember that */
+        ClientPort->Flags |= LPCP_SECURITY_DYNAMIC;
+    }
+    else
+    {
+        /* Create our own client security */
+        Status = SeCreateClientSecurity(Thread,
+                                        Qos,
+                                        FALSE,
+                                        &ClientPort->StaticSecurity);
+        if (!NT_SUCCESS(Status))
         {
-          RtlCopyMemory(&WriteMap,
-                        UnsafeWriteMap,
-                        sizeof(PORT_VIEW));
+            /* Security failed, dereference and return */
+            ObDereferenceObject(ClientPort);
+            return Status;
         }
-
-      if (WriteMap.Length != sizeof(PORT_VIEW))
-       {
-         return(STATUS_INVALID_PARAMETER_4);
-       }
-      SectionOffset.QuadPart = WriteMap.SectionOffset;
     }
-  else
+
+    /* Initialize the port queue */
+    Status = LpcpInitializePortQueue(ClientPort);
+    if (!NT_SUCCESS(Status))
     {
-      WriteMap.SectionHandle = INVALID_HANDLE_VALUE;
+        /* Failed */
+        ObDereferenceObject(ClientPort);
+        return Status;
     }
 
-  /*
-   * Handle connection data.
-   */
-  if (UnsafeConnectData)
+    /* Check if we have a client view */
+    if (ClientView)
     {
-      if (PreviousMode != KernelMode)
+        /* Get the section handle */
+        Status = ObReferenceObjectByHandle(ClientView->SectionHandle,
+                                           SECTION_MAP_READ |
+                                           SECTION_MAP_WRITE,
+                                           MmSectionObjectType,
+                                           PreviousMode,
+                                           (PVOID*)&SectionToMap,
+                                           NULL);
+        if (!NT_SUCCESS(Status))
         {
-          _SEH_TRY
-            {
-              ConnectDataLength = ProbeForReadUlong(UnsafeConnectDataLength);
-            }
-          _SEH_HANDLE
-            {
-              Status = _SEH_GetExceptionCode();
-            }
-          _SEH_END;
-
-          if (!NT_SUCCESS(Status))
-            {
-              return Status;
-            }
-        }
-      else
-        {
-          ConnectDataLength = *UnsafeConnectDataLength;
+            /* Fail */
+            ObDereferenceObject(Port);
+            return Status;
         }
 
-      if (ConnectDataLength != 0)
-        {
-          ConnectData = ExAllocatePool(NonPagedPool, ConnectDataLength);
-          if (ConnectData == NULL)
-            {
-              return(STATUS_NO_MEMORY);
-            }
+        /* Set the section offset */
+        SectionOffset.QuadPart = ClientView->SectionOffset;
 
-          if (PreviousMode != KernelMode)
-            {
-              _SEH_TRY
-                {
-                  ProbeForWriteUlong(UnsafeConnectData);
-                  RtlCopyMemory(ConnectData,
-                                UnsafeConnectData,
-                                ConnectDataLength);
-                }
-              _SEH_HANDLE
-                {
-                  Status = _SEH_GetExceptionCode();
-                }
-              _SEH_END;
+        /* Map it */
+        Status = MmMapViewOfSection(SectionToMap,
+                                    PsGetCurrentProcess(),
+                                    &Port->ClientSectionBase,
+                                    0,
+                                    0,
+                                    &SectionOffset,
+                                    &ClientView->ViewSize,
+                                    ViewUnmap,
+                                    0,
+                                    PAGE_READWRITE);
 
-              if (!NT_SUCCESS(Status))
-                {
-                  ExFreePool(ConnectData);
-                  return Status;
-                }
-            }
-          else
-            {
-              RtlCopyMemory(ConnectData,
-                            UnsafeConnectData,
-                            ConnectDataLength);
-            }
+        /* Update the offset */
+        ClientView->SectionOffset = SectionOffset.LowPart;
+
+        /* Check for failure */
+        if (!NT_SUCCESS(Status))
+        {
+            /* Fail */
+            ObDereferenceObject(SectionToMap);
+            ObDereferenceObject(Port);
+            return Status;
         }
-    }
 
-  /*
-   * Reference the named port.
-   */
-  Status = ObReferenceObjectByName (PortName,
-                                    0,
-                                    NULL,
-                                    PORT_ALL_ACCESS,  /* DesiredAccess */
-                                    LpcPortObjectType,
-                                    PreviousMode,
-                                    NULL,
-                                    (PVOID*)&NamedPort);
-  if (!NT_SUCCESS(Status))
+        /* Update the base */
+        ClientView->ViewBase = Port->ClientSectionBase;
+    }
+    else
     {
-      if (KeGetPreviousMode() != KernelMode)
-       {
-         ExFreePool(ConnectData);
-       }
-      return(Status);
+        /* No section */
+        SectionToMap = NULL;
     }
 
-  /*
-   * Reference the send section object.
-   */
-  if (WriteMap.SectionHandle != INVALID_HANDLE_VALUE)
+    /* Normalize connection information */
+    if (ConnectionInfoLength > Port->MaxConnectionInfoLength)
     {
-      Status = ObReferenceObjectByHandle(WriteMap.SectionHandle,
-                                        SECTION_MAP_READ | SECTION_MAP_WRITE,
-                                        MmSectionObjectType,
-                                        PreviousMode,
-                                        (PVOID*)&SectionObject,
-                                        NULL);
-      if (!NT_SUCCESS(Status))
-       {
-         ObDereferenceObject(NamedPort);
-         if (KeGetPreviousMode() != KernelMode)
-           {
-             ExFreePool(ConnectData);
-           }
-         return(Status);
-       }
+        /* Use the port's maximum allowed value */
+        ConnectionInfoLength = Port->MaxConnectionInfoLength;
     }
-  else
+
+    /* Allocate a message from the port zone */
+    Message = LpcpAllocateFromPortZone();
+    if (!Message)
     {
-      SectionObject = NULL;
+        /* Fail if we couldn't allocate a message */
+        if (SectionToMap) ObDereferenceObject(SectionToMap);
+        ObDereferenceObject(ClientPort);
+        return STATUS_NO_MEMORY;
     }
 
-  /*
-   * Do the connection establishment.
-   */
-  Status = EiConnectPort(&ConnectedPort,
-                        NamedPort,
-                        SectionObject,
-                        SectionOffset,
-                        WriteMap.ViewSize,
-                        &WriteMap.ViewBase,
-                        &WriteMap.ViewRemoteBase,
-                        &ReadMap.ViewSize,
-                        &ReadMap.ViewBase,
-                        &MaximumMessageSize,
-                        ConnectData,
-                        &ConnectDataLength);
-  if (!NT_SUCCESS(Status))
+    /* Set pointer to the connection message and fill in the CID */
+    ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(Message + 1);
+    Message->Request.ClientId = Thread->Cid;
+
+    /* Check if we have a client view */
+    if (ClientView)
     {
-      /* FIXME: Again, check what NT does here. */
-      if (UnsafeConnectDataLength != NULL)
-       {
-         if (PreviousMode != KernelMode)
-           {
-              _SEH_TRY
-                {
-                  RtlCopyMemory(UnsafeConnectData,
-                                ConnectData,
-                                ConnectDataLength);
-                  *UnsafeConnectDataLength = ConnectDataLength;
-                }
-              _SEH_HANDLE
-                {
-                  Status = _SEH_GetExceptionCode();
-                }
-              _SEH_END;
-           }
-         else
-           {
-               RtlCopyMemory(UnsafeConnectData,
-                             ConnectData,
-                             ConnectDataLength);
-               *UnsafeConnectDataLength = ConnectDataLength;
-           }
-
-          ExFreePool(ConnectData);
-       }
-      return(Status);
-    }
+        /* Set the view size */
+        Message->Request.ClientViewSize = ClientView->ViewSize;
 
-  /*
-   * Do some initial cleanup.
-   */
-  if (SectionObject != NULL)
+        /* Copy the client view and clear the server view */
+        RtlMoveMemory(&ConnectMessage->ClientView,
+                      ClientView,
+                      sizeof(PORT_VIEW));
+        RtlZeroMemory(&ConnectMessage->ServerView, sizeof(REMOTE_PORT_VIEW));
+    }
+    else
     {
-      ObDereferenceObject(SectionObject);
-      SectionObject = NULL;
+        /* Set the size to 0 and clear the connect message */
+        Message->Request.ClientViewSize = 0;
+        RtlZeroMemory(ConnectMessage, sizeof(LPCP_CONNECTION_MESSAGE));
     }
-  ObDereferenceObject(NamedPort);
-  NamedPort = NULL;
 
-  /*
-   * Copy the data back to the caller.
-   */
+    /* Set the section and client port. Port is NULL for now */
+    ConnectMessage->ClientPort = NULL;
+    ConnectMessage->SectionToMap = SectionToMap;
+
+    /* Set the data for the connection request message */
+    Message->Request.u1.s1.DataLength = sizeof(LPCP_CONNECTION_MESSAGE) +
+                                        ConnectionInfoLength;
+    Message->Request.u1.s1.TotalLength = sizeof(LPCP_MESSAGE) +
+                                         Message->Request.u1.s1.DataLength;
+    Message->Request.u2.s2.Type = LPC_CONNECTION_REQUEST;
 
-  if (UnsafeConnectDataLength != NULL)
+    /* Check if we have connection information */
+    if (ConnectionInformation)
     {
-      if (PreviousMode != KernelMode)
-       {
-          _SEH_TRY
-            {
-              *UnsafeConnectDataLength = ConnectDataLength;
-              
-              if (ConnectData != NULL)
-                {
-                  RtlCopyMemory(UnsafeConnectData,
-                                ConnectData,
-                                ConnectDataLength);
-                }
-            }
-          _SEH_HANDLE
-            {
-              Status = _SEH_GetExceptionCode();
-            }
-          _SEH_END;
+        /* Copy it in */
+        RtlMoveMemory(ConnectMessage + 1,
+                      ConnectionInformation,
+                      ConnectionInfoLength);
+    }
 
-         if (!NT_SUCCESS(Status))
-           {
-              if (ConnectData != NULL)
-                {
-                  ExFreePool(ConnectData);
-                }
-              return(Status);
-           }
-       }
-      else
-        {
-          *UnsafeConnectDataLength = ConnectDataLength;
-          
-          if (ConnectData != NULL)
-            {
-              RtlCopyMemory(UnsafeConnectData,
-                            ConnectData,
-                            ConnectDataLength);
-            }
-        }
+    /* Acquire the port lock */
+    KeAcquireGuardedMutex(&LpcpLock);
 
-      if (ConnectData != NULL)
-       {
-         ExFreePool(ConnectData);
-       }
-    }
-  Status = ObInsertObject(ConnectedPort,
-                         NULL,
-                         PORT_ALL_ACCESS,
-                         1,
-                         (PVOID*)&ConnectedPort,
-                         &ConnectedPortHandle);
-  if (!NT_SUCCESS(Status))
+    /* Check if someone already deleted the port name */
+    if (Port->Flags & LPCP_NAME_DELETED)
     {
-      return(Status);
+        /* Fail the request */
+        KeReleaseGuardedMutex(&LpcpLock);
+        Status = STATUS_OBJECT_NAME_NOT_FOUND;
+        goto Cleanup;
     }
 
-  if (PreviousMode != KernelMode)
-    {
-      _SEH_TRY
-        {
-          *UnsafeConnectedPortHandle = ConnectedPortHandle;
-          
-          if (UnsafeWriteMap != NULL)
-            {
-              RtlCopyMemory(UnsafeWriteMap,
-                            &WriteMap,
-                            sizeof(PORT_VIEW));
-            }
+    /* Associate no thread yet */
+    Message->RepliedToThread = NULL;
 
-          if (UnsafeReadMap != NULL)
-            {
-              RtlCopyMemory(UnsafeReadMap,
-                            &ReadMap,
-                            sizeof(REMOTE_PORT_VIEW));
-            }
+    /* Generate the Message ID and set it */
+    Message->Request.MessageId =  LpcpNextMessageId++;
+    if (!LpcpNextMessageId) LpcpNextMessageId = 1;
+    Thread->LpcReplyMessageId = Message->Request.MessageId;
 
-          if (UnsafeMaximumMessageSize != NULL)
-            {
-              *UnsafeMaximumMessageSize = MaximumMessageSize;
-            }
-        }
-      _SEH_HANDLE
-        {
-          Status = _SEH_GetExceptionCode();
-        }
-      _SEH_END;
-      
-      if (!NT_SUCCESS(Status))
-        {
-          return Status;
-        }
-    }
-  else
+    /* Insert the message into the queue and thread chain */
+    InsertTailList(&Port->MsgQueue.ReceiveHead, &Message->Entry);
+    InsertTailList(&Port->LpcReplyChainHead, &Thread->LpcReplyChain);
+    Thread->LpcReplyMessage = Message;
+
+    /* Now we can finally reference the client port and link it*/
+    ObReferenceObject(ClientPort);
+    ConnectMessage->ClientPort = ClientPort;
+
+    /* Release the lock */
+    KeReleaseGuardedMutex(&LpcpLock);
+    LPCTRACE(LPC_CONNECT_DEBUG,
+             "Messages: %p/%p. Ports: %p/%p. Status: %lx\n",
+             Message,
+             ConnectMessage,
+             Port,
+             ClientPort,
+             Status);
+
+    /* If this is a waitable port, set the event */
+    if (Port->Flags & LPCP_WAITABLE_PORT) KeSetEvent(&Port->WaitEvent,
+                                                     1,
+                                                     FALSE);
+
+    /* Release the queue semaphore */
+    LpcpCompleteWait(Port->MsgQueue.Semaphore);
+
+    /* Now wait for a reply */
+    LpcpConnectWait(&Thread->LpcReplySemaphore, PreviousMode);
+
+    /* Check if our wait ended in success */
+    if (Status != STATUS_SUCCESS) goto Cleanup;
+
+    /* Free the connection message */
+    SectionToMap = LpcpFreeConMsg(&Message, &ConnectMessage, Thread);
+
+    /* Check if we got a message back */
+    if (Message)
     {
-      *UnsafeConnectedPortHandle = ConnectedPortHandle;
-      
-      if (UnsafeWriteMap != NULL)
+        /* Check for new return length */
+        if ((Message->Request.u1.s1.DataLength -
+             sizeof(LPCP_CONNECTION_MESSAGE)) < ConnectionInfoLength)
         {
-          RtlCopyMemory(UnsafeWriteMap,
-                        &WriteMap,
-                        sizeof(PORT_VIEW));
+            /* Set new normalized connection length */
+            ConnectionInfoLength = Message->Request.u1.s1.DataLength -
+                                   sizeof(LPCP_CONNECTION_MESSAGE);
         }
 
-      if (UnsafeReadMap != NULL)
+        /* Check if we had connection information */
+        if (ConnectionInformation)
         {
-          RtlCopyMemory(UnsafeReadMap,
-                        &ReadMap,
-                        sizeof(REMOTE_PORT_VIEW));
-        }
+            /* Check if we had a length pointer */
+            if (ConnectionInformationLength)
+            {
+                /* Return the length */
+                *ConnectionInformationLength = ConnectionInfoLength;
+            }
 
-      if (UnsafeMaximumMessageSize != NULL)
-        {
-          *UnsafeMaximumMessageSize = MaximumMessageSize;
+            /* Return the connection information */
+            RtlMoveMemory(ConnectionInformation,
+                          ConnectMessage + 1,
+                          ConnectionInfoLength );
         }
-    }
 
-  /*
-   * All done.
-   */
+        /* Make sure we had a connected port */
+        if (ClientPort->ConnectedPort)
+        {
+            /* Get the message length before the port might get killed */
+            PortMessageLength = Port->MaxMessageLength;
 
-  return(STATUS_SUCCESS);
-}
+            /* Insert the client port */
+            Status = ObInsertObject(ClientPort,
+                                    NULL,
+                                    PORT_ALL_ACCESS,
+                                    0,
+                                    (PVOID *)NULL,
+                                    &Handle);
+            if (NT_SUCCESS(Status))
+            {
+                /* Return the handle */
+                *PortHandle = Handle;
+                LPCTRACE(LPC_CONNECT_DEBUG,
+                         "Handle: %lx. Length: %lx\n",
+                         Handle,
+                         PortMessageLength);
+
+                /* Check if maximum length was requested */
+                if (MaxMessageLength) *MaxMessageLength = PortMessageLength;
+
+                /* Check if we had a client view */
+                if (ClientView)
+                {
+                    /* Copy it back */
+                    RtlMoveMemory(ClientView,
+                                  &ConnectMessage->ClientView,
+                                  sizeof(PORT_VIEW));
+                }
 
+                /* Check if we had a server view */
+                if (ServerView)
+                {
+                    /* Copy it back */
+                    RtlMoveMemory(ServerView,
+                                  &ConnectMessage->ServerView,
+                                  sizeof(REMOTE_PORT_VIEW));
+                }
+            }
+        }
+        else
+        {
+            /* No connection port, we failed */
+            if (SectionToMap) ObDereferenceObject(SectionToMap);
 
-/**********************************************************************
- * NAME                                                        EXPORTED
- *     NtAcceptConnectPort/6
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- *     ServerPortHandle
- *     NamedPortHandle
- *     LpcMessage
- *     AcceptIt
- *     WriteMap
- *     ReadMap
- *
- * RETURN VALUE
- */
-/*EXPORTED*/ NTSTATUS STDCALL
-NtAcceptConnectPort (PHANDLE                   ServerPortHandle,
-                    HANDLE                     NamedPortHandle,
-                    PPORT_MESSAGE              LpcMessage,
-                    BOOLEAN                    AcceptIt,
-                    PPORT_VIEW WriteMap,
-                    PREMOTE_PORT_VIEW  ReadMap)
-{
-  NTSTATUS     Status;
-  PEPORT               NamedPort;
-  PEPORT               OurPort = NULL;
-  PQUEUEDMESSAGE       ConnectionRequest;
-  KIRQL                oldIrql;
-  PEPORT_CONNECT_REQUEST_MESSAGE CRequest;
-  PEPORT_CONNECT_REPLY_MESSAGE CReply;
-  ULONG Size;
-  KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
-
-  Size = sizeof(EPORT_CONNECT_REPLY_MESSAGE);
-  if (LpcMessage)
-  {
-     Size += LpcMessage->u1.s1.DataLength;
-  }
-
-  CReply = ExAllocatePool(NonPagedPool, Size);
-  if (CReply == NULL)
-    {
-      return(STATUS_NO_MEMORY);
-    }
+            /* Check if it's because the name got deleted */
+            if (Port->Flags & LPCP_NAME_DELETED)
+            {
+                /* Set the correct status */
+                Status = STATUS_OBJECT_NAME_NOT_FOUND;
+            }
+            else
+            {
+                /* Otherwise, the caller refused us */
+                Status = STATUS_PORT_CONNECTION_REFUSED;
+            }
 
-  Status = ObReferenceObjectByHandle(NamedPortHandle,
-                                    PORT_ALL_ACCESS,
-                                    LpcPortObjectType,
-                                    PreviousMode,
-                                    (PVOID*)&NamedPort,
-                                    NULL);
-  if (!NT_SUCCESS(Status))
-    {
-      ExFreePool(CReply);
-      return (Status);
-    }
+            /* Kill the port */
+            ObDereferenceObject(ClientPort);
+        }
 
-  /*
-   * Create a port object for our side of the connection
-   */
-  if (AcceptIt)
-    {
-      Status = ObCreateObject(PreviousMode,
-                             LpcPortObjectType,
-                             NULL,
-                             PreviousMode,
-                             NULL,
-                             sizeof(EPORT),
-                             0,
-                             0,
-                             (PVOID*)&OurPort);
-      if (!NT_SUCCESS(Status))
-       {
-         ExFreePool(CReply);
-         ObDereferenceObject(NamedPort);
-         return(Status);
-       }
-
-      Status = ObInsertObject ((PVOID)OurPort,
-                              NULL,
-                              PORT_ALL_ACCESS,
-                              0,
-                              NULL,
-                              ServerPortHandle);
-      if (!NT_SUCCESS(Status))
-       {
-         ObDereferenceObject(OurPort);
-         ExFreePool(CReply);
-         ObDereferenceObject(NamedPort);
-         return(Status);
-       }
-
-      LpcpInitializePort(OurPort, EPORT_TYPE_SERVER_COMM_PORT, NamedPort);
+        /* Free the message */
+        LpcpFreeToPortZone(Message, FALSE);
+        return Status;
     }
 
-  /*
-   * Dequeue the connection request
-   */
-  KeAcquireSpinLock(&NamedPort->Lock, &oldIrql);
-  ConnectionRequest = EiDequeueConnectMessagePort (NamedPort);
-  KeReleaseSpinLock(&NamedPort->Lock, oldIrql);
-  CRequest = (PEPORT_CONNECT_REQUEST_MESSAGE)(&ConnectionRequest->Message);
-
-  /*
-   * Prepare the reply.
-   */
-  if (LpcMessage != NULL)
-    {
-      memcpy(&CReply->MessageHeader, LpcMessage, sizeof(PORT_MESSAGE));
-      memcpy(&CReply->ConnectData, (PVOID)(LpcMessage + 1),
-            LpcMessage->u1.s1.DataLength);
-      CReply->MessageHeader.u1.s1.TotalLength =
-       sizeof(EPORT_CONNECT_REPLY_MESSAGE) + LpcMessage->u1.s1.DataLength;
-      CReply->MessageHeader.u1.s1.DataLength = CReply->MessageHeader.u1.s1.TotalLength -
-       sizeof(PORT_MESSAGE);
-      CReply->ConnectDataLength = LpcMessage->u1.s1.DataLength;
-    }
-  else
-    {
-      CReply->MessageHeader.u1.s1.TotalLength = sizeof(EPORT_CONNECT_REPLY_MESSAGE);
-      CReply->MessageHeader.u1.s1.DataLength = sizeof(EPORT_CONNECT_REPLY_MESSAGE) -
-       sizeof(PORT_MESSAGE);
-      CReply->ConnectDataLength = 0;
-    }
-  if (!AcceptIt)
-    {
-      EiReplyOrRequestPort(ConnectionRequest->Sender,
-                          &CReply->MessageHeader,
-                          LPC_CONNECTION_REFUSED,
-                          NamedPort);
-      KeReleaseSemaphore(&ConnectionRequest->Sender->Semaphore,
-                        IO_NO_INCREMENT,
-                        1,
-                        FALSE);
-      ObDereferenceObject(ConnectionRequest->Sender);
-      ExFreePool(ConnectionRequest);
-      ExFreePool(CReply);
-      ObDereferenceObject(NamedPort);
-      return (STATUS_SUCCESS);
-    }
+    /* No reply message, fail */
+    if (SectionToMap) ObDereferenceObject(SectionToMap);
+    ObDereferenceObject(ClientPort);
+    return STATUS_PORT_CONNECTION_REFUSED;
 
-  /*
-   * Prepare the connection.
-   */
-  if (WriteMap != NULL)
-    {
-      PVOID SectionObject;
-      LARGE_INTEGER SectionOffset;
-
-      Status = ObReferenceObjectByHandle(WriteMap->SectionHandle,
-                                        SECTION_MAP_READ | SECTION_MAP_WRITE,
-                                        MmSectionObjectType,
-                                        PreviousMode,
-                                        (PVOID*)&SectionObject,
-                                        NULL);
-      if (!NT_SUCCESS(Status))
-       {
-         return(Status);
-       }
-
-      SectionOffset.QuadPart = WriteMap->SectionOffset;
-      WriteMap->ViewRemoteBase = 0;
-      CReply->ReceiveClientViewSize = WriteMap->ViewSize;
-      Status = MmMapViewOfSection(SectionObject,
-                                 CRequest->ConnectingProcess,
-                                 &WriteMap->ViewRemoteBase,
-                                 0,
-                                 CReply->ReceiveClientViewSize,
-                                 &SectionOffset,
-                                 &CReply->ReceiveClientViewSize,
-                                 ViewUnmap,
-                                 0 /* MEM_TOP_DOWN? */,
-                                 PAGE_READWRITE);
-      if (!NT_SUCCESS(Status))
-       {
-         return(Status);
-       }
-
-      WriteMap->ViewBase = 0;
-      Status = MmMapViewOfSection(SectionObject,
-                                 PsGetCurrentProcess(),
-                                 &WriteMap->ViewBase,
-                                 0,
-                                 WriteMap->ViewSize,
-                                 &SectionOffset,
-                                 &WriteMap->ViewSize,
-                                 ViewUnmap,
-                                 0 /* MEM_TOP_DOWN? */,
-                                 PAGE_READWRITE);
-      if (!NT_SUCCESS(Status))
-       {
-         return(Status);
-       }
-
-      ObDereferenceObject(SectionObject);
-    }
-  if (ReadMap != NULL && CRequest->SendSectionObject != NULL)
-    {
-      LARGE_INTEGER SectionOffset;
-
-      SectionOffset = CRequest->SendSectionOffset;
-      ReadMap->ViewSize = CRequest->SendViewSize;
-      ReadMap->ViewBase = 0;
-      Status = MmMapViewOfSection(CRequest->SendSectionObject,
-                                 PsGetCurrentProcess(),
-                                 &ReadMap->ViewBase,
-                                 0,
-                                 CRequest->SendViewSize,
-                                 &SectionOffset,
-                                 &CRequest->SendViewSize,
-                                 ViewUnmap,
-                                 0 /* MEM_TOP_DOWN? */,
-                                 PAGE_READWRITE);
-      if (!NT_SUCCESS(Status))
-       {
-         return(Status);
-       }
-    }
+Cleanup:
+    /* We failed, free the message */
+    SectionToMap = LpcpFreeConMsg(&Message, &ConnectMessage, Thread);
 
-  /*
-   * Finish the reply.
-   */
-  if (ReadMap != NULL)
+    /* Check if the semaphore got signaled */
+    if (KeReadStateSemaphore(&Thread->LpcReplySemaphore))
     {
-      CReply->SendServerViewBase = ReadMap->ViewBase;
+        /* Wait on it */
+        KeWaitForSingleObject(&Thread->LpcReplySemaphore,
+                              KernelMode,
+                              Executive,
+                              FALSE,
+                              NULL);
     }
-  else
-    {
-      CReply->SendServerViewBase = 0;
-    }
-  if (WriteMap != NULL)
-    {
-      CReply->ReceiveClientViewBase = WriteMap->ViewRemoteBase;
-    }
-  CReply->MaximumMessageSize = LPC_MAX_MESSAGE_LENGTH;
-
 
-  /*
-   * Connect the two ports
-   */
-  OurPort->OtherPort = ConnectionRequest->Sender;
-  OurPort->OtherPort->OtherPort = OurPort;
-  EiReplyOrRequestPort(ConnectionRequest->Sender,
-                      (PPORT_MESSAGE)CReply,
-                      LPC_REPLY,
-                      OurPort);
-  ExFreePool(ConnectionRequest);
-  ExFreePool(CReply);
+    /* Check if we had a message and free it */
+    if (Message) LpcpFreeToPortZone(Message, FALSE);
 
-  //ObDereferenceObject(OurPort);
-  ObDereferenceObject(NamedPort);
+    /* Dereference other objects */
+    if (SectionToMap) ObDereferenceObject(SectionToMap);
+    ObDereferenceObject(ClientPort);
 
-  return (STATUS_SUCCESS);
+    /* Return status */
+    return Status;
 }
 
-/**********************************************************************
- * NAME                                                        EXPORTED
- *     NtSecureConnectPort/9
- *
- * DESCRIPTION
- *     Connect to a named port and wait for the other side to
- *     accept the connection. Possibly verify that the server
- *     matches the ServerSid (trusted server).
- *     Present in w2k+.
- *
- * ARGUMENTS
- *     ConnectedPort
- *     PortName: fully qualified name in the Ob name space;
- *     Qos
- *     WriteMap
- *     ServerSid
- *     ReadMap
- *     MaxMessageSize
- *     ConnectInfo
- *     UserConnectInfoLength
- *
- * RETURN VALUE
+/*
+ * @implemented
  */
-NTSTATUS STDCALL
-NtSecureConnectPort (OUT    PHANDLE                            ConnectedPort,
-                    IN     PUNICODE_STRING                     PortName,
-                    IN     PSECURITY_QUALITY_OF_SERVICE        Qos,
-                    IN OUT PPORT_VIEW                  WriteMap                OPTIONAL,
-                    IN     PSID                                ServerSid               OPTIONAL,
-                    IN OUT PREMOTE_PORT_VIEW                   ReadMap                 OPTIONAL,
-                    OUT    PULONG                              MaxMessageSize          OPTIONAL,
-                    IN OUT PVOID                               ConnectInfo             OPTIONAL,
-                    IN OUT PULONG                              UserConnectInfoLength   OPTIONAL)
+NTSTATUS
+NTAPI
+NtConnectPort(OUT PHANDLE PortHandle,
+              IN PUNICODE_STRING PortName,
+              IN PSECURITY_QUALITY_OF_SERVICE Qos,
+              IN PPORT_VIEW ClientView,
+              IN PREMOTE_PORT_VIEW ServerView,
+              OUT PULONG MaxMessageLength,
+              IN PVOID ConnectionInformation,
+              OUT PULONG ConnectionInformationLength)
 {
-  /* TODO: implement a new object type: WaitablePort */
-  /* TODO: verify the process' SID that hosts the rendez-vous port equals ServerSid */
-  return NtConnectPort (ConnectedPort,
-                       PortName,
-                       Qos,
-                       WriteMap,
-                       ReadMap,
-                       MaxMessageSize,
-                       ConnectInfo,
-                       UserConnectInfoLength);
+    /* Call the newer API */
+    return NtSecureConnectPort(PortHandle,
+                               PortName,
+                               Qos,
+                               ClientView,
+                               NULL,
+                               ServerView,
+                               MaxMessageLength,
+                               ConnectionInformation,
+                               ConnectionInformationLength);
 }
 
 /* EOF */
index 1fcefa0..2bf08c1 100644 (file)
-/* $Id$
- *
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS kernel
+/*
+ * PROJECT:         ReactOS Kernel
+ * LICENSE:         GPL - See COPYING in the top level directory
  * FILE:            ntoskrnl/lpc/create.c
- * PURPOSE:         Communication mechanism
- *
- * PROGRAMMERS:     David Welch (welch@cwcom.net)
+ * PURPOSE:         Local Procedure Call: Port/Queue/Message Creation
+ * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
  */
 
-/* INCLUDES *****************************************************************/
+/* INCLUDES ******************************************************************/
 
 #include <ntoskrnl.h>
+#include "lpc.h"
 #define NDEBUG
 #include <internal/debug.h>
 
-/**********************************************************************
- * NAME
- *     LpcpVerifyCreateParameters/5
- *
- * DESCRIPTION
- *     Verify user parameters in NtCreatePort and in
- *     NtCreateWaitablePort.
- *
- * ARGUMENTS
- *
- * RETURN VALUE
- */
-static NTSTATUS STDCALL
-LpcpVerifyCreateParameters (IN PHANDLE                 PortHandle,
-                           IN  POBJECT_ATTRIBUTES      ObjectAttributes,
-                           IN  ULONG                   MaxConnectInfoLength,
-                           IN  ULONG                   MaxDataLength,
-                           IN  ULONG                   MaxPoolUsage)
+/* PRIVATE FUNCTIONS *********************************************************/
+
+NTSTATUS
+NTAPI
+LpcpInitializePortQueue(IN PLPCP_PORT_OBJECT Port)
 {
-  if (NULL == PortHandle)
-    {
-      return (STATUS_INVALID_PARAMETER_1);
-    }
-  if (NULL == ObjectAttributes)
+    PLPCP_NONPAGED_PORT_QUEUE MessageQueue;
+
+    /* Allocate the queue */
+    MessageQueue = ExAllocatePoolWithTag(NonPagedPool,
+                                         sizeof(LPCP_NONPAGED_PORT_QUEUE),
+                                         TAG('P', 'o', 'r', 't'));
+    if (!MessageQueue) return STATUS_INSUFFICIENT_RESOURCES;
+
+    /* Set it up */
+    KeInitializeSemaphore(&MessageQueue->Semaphore, 0, MAXLONG);
+    MessageQueue->BackPointer = Port;
+
+    /* And link it with the Paged Pool part */
+    Port->MsgQueue.Semaphore = &MessageQueue->Semaphore;
+    InitializeListHead(&Port->MsgQueue.ReceiveHead);
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+LpcpCreatePort(OUT PHANDLE PortHandle,
+               IN POBJECT_ATTRIBUTES ObjectAttributes,
+               IN ULONG MaxConnectionInfoLength,
+               IN ULONG MaxMessageLength,
+               IN ULONG MaxPoolUsage,
+               IN BOOLEAN Waitable)
+{
+    KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
+    NTSTATUS Status;
+    PLPCP_PORT_OBJECT Port;
+    LPCTRACE(LPC_CREATE_DEBUG, "Name: %wZ\n", ObjectAttributes->ObjectName);
+
+    /* Create the Object */
+    Status = ObCreateObject(PreviousMode,
+                            LpcPortObjectType,
+                            ObjectAttributes,
+                            PreviousMode,
+                            NULL,
+                            sizeof(LPCP_PORT_OBJECT),
+                            0,
+                            0,
+                            (PVOID*)&Port);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    /* Set up the Object */
+    RtlZeroMemory(Port, sizeof(LPCP_PORT_OBJECT));
+    Port->ConnectionPort = Port;
+    Port->Creator = PsGetCurrentThread()->Cid;
+    InitializeListHead(&Port->LpcDataInfoChainHead);
+    InitializeListHead(&Port->LpcReplyChainHead);
+
+    /* Check if we don't have a name */
+    if (!ObjectAttributes->ObjectName->Buffer)
     {
-      return (STATUS_INVALID_PARAMETER_2);
+        /* Set up for an unconnected port */
+        Port->Flags = LPCP_UNCONNECTED_PORT;
+        Port->ConnectedPort = Port;
+        Port->ServerProcess = NULL;
     }
-  if ((ObjectAttributes->Attributes    & OBJ_OPENLINK)
-      || (ObjectAttributes->Attributes & OBJ_OPENIF)
-      || (ObjectAttributes->Attributes & OBJ_EXCLUSIVE)
-      || (ObjectAttributes->Attributes & OBJ_PERMANENT)
-      || (ObjectAttributes->Attributes & OBJ_INHERIT))
-  {
-    return (STATUS_INVALID_PORT_ATTRIBUTES);
-  }
-  if (MaxConnectInfoLength > LPC_MAX_DATA_LENGTH)
+    else
     {
-      return (STATUS_INVALID_PARAMETER_3);
+        /* Set up for a named connection port */
+        Port->Flags = LPCP_CONNECTION_PORT;
+        Port->ServerProcess = PsGetCurrentProcess();
+
+        /* Don't let the process die on us */
+        ObReferenceObject(Port->ServerProcess);
     }
-  if (MaxDataLength > LPC_MAX_MESSAGE_LENGTH)
+
+    /* Check if this is a waitable port */
+    if (Waitable) Port->Flags |= LPCP_WAITABLE_PORT;
+
+    /* Setup the port queue */
+    Status = LpcpInitializePortQueue(Port);
+    if (!NT_SUCCESS(Status))
     {
-      return (STATUS_INVALID_PARAMETER_4);
+        /* Fail */
+        ObDereferenceObject(Port);
+        return Status;
     }
-  /* TODO: some checking is done also on MaxPoolUsage
-   * to avoid choking the executive */
-  return (STATUS_SUCCESS);
-}
 
-/**********************************************************************
- * NAME                                                        EXPORTED
- *     NtCreatePort/5
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- *     PortHandle,
- *     ObjectAttributes,
- *     MaxConnectInfoLength,
- *     MaxDataLength,
- *     MaxPoolUsage: size of NP zone the NP part of msgs is kept in
- *
- * RETURN VALUE
- */
-/*EXPORTED*/ NTSTATUS STDCALL
-NtCreatePort (PHANDLE                PortHandle,
-             POBJECT_ATTRIBUTES    ObjectAttributes,
-             ULONG            MaxConnectInfoLength,
-             ULONG                     MaxDataLength,
-             ULONG                     MaxPoolUsage)
-{
-  PEPORT               Port;
-  NTSTATUS     Status;
-
-  DPRINT("NtCreatePort() Name %x\n", ObjectAttributes->ObjectName->Buffer);
-
-  /* Verify parameters */
-  Status = LpcpVerifyCreateParameters (PortHandle,
-                                      ObjectAttributes,
-                                      MaxConnectInfoLength,
-                                      MaxDataLength,
-                                      MaxPoolUsage);
-  if (STATUS_SUCCESS != Status)
+    /* Check if this is a waitable port */
+    if (Port->Flags & LPCP_WAITABLE_PORT)
     {
-      return (Status);
+        /* Setup the wait event */
+        KeInitializeEvent(&Port->WaitEvent, NotificationEvent, FALSE);
     }
 
-  /* Ask Ob to create the object */
-  Status = ObCreateObject (ExGetPreviousMode(),
-                          LpcPortObjectType,
-                          ObjectAttributes,
-                          ExGetPreviousMode(),
-                          NULL,
-                          sizeof(EPORT),
-                          0,
-                          0,
-                          (PVOID*)&Port);
-  if (!NT_SUCCESS(Status))
+    /* Set the maximum message size allowed */
+    Port->MaxMessageLength = LpcpMaxMessageSize -
+                             FIELD_OFFSET(LPCP_MESSAGE, Request);
+
+    /* Now subtract the actual message structures and get the data size */
+    Port->MaxConnectionInfoLength = Port->MaxMessageLength -
+                                    sizeof(PORT_MESSAGE) -
+                                    sizeof(LPCP_CONNECTION_MESSAGE);
+
+    /* Validate the sizes */
+    if (Port->MaxConnectionInfoLength < MaxConnectionInfoLength)
     {
-      return (Status);
+        /* Not enough space for your request */
+        ObDereferenceObject(Port);
+        return STATUS_INVALID_PARAMETER_3;
     }
-
-  Status = ObInsertObject ((PVOID)Port,
-                          NULL,
-                          PORT_ALL_ACCESS,
-                          0,
-                          NULL,
-                          PortHandle);
-  if (!NT_SUCCESS(Status))
+    else if (Port->MaxMessageLength < MaxMessageLength)
     {
-      ObDereferenceObject (Port);
-      return (Status);
+        /* Not enough space for your request */
+        ObDereferenceObject(Port);
+        return STATUS_INVALID_PARAMETER_4;
     }
 
-  Status = LpcpInitializePort (Port, EPORT_TYPE_SERVER_RQST_PORT, NULL);
-  Port->MaxConnectInfoLength = LPC_MAX_DATA_LENGTH;
-  Port->MaxDataLength = LPC_MAX_MESSAGE_LENGTH;
-  Port->MaxPoolUsage = MaxPoolUsage;
+    /* Now set the custom setting */
+    Port->MaxMessageLength = MaxMessageLength;
+
+    /* Insert it now */
+    Status = ObInsertObject((PVOID)Port,
+                            NULL,
+                            PORT_ALL_ACCESS,
+                            0,
+                            NULL,
+                            PortHandle);
+
+    /* Return success or the error */
+    LPCTRACE(LPC_CREATE_DEBUG, "Port: %p. Handle: %lx\n", Port, *PortHandle);
+    return Status;
+}
+
+/* PUBLIC FUNCTIONS **********************************************************/
+
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+NtCreatePort(OUT PHANDLE PortHandle,
+             IN POBJECT_ATTRIBUTES ObjectAttributes,
+             IN ULONG MaxConnectInfoLength,
+             IN ULONG MaxDataLength,
+             IN ULONG MaxPoolUsage)
+{
+    PAGED_CODE();
 
-  return (Status);
+    /* Call the internal API */
+    return LpcpCreatePort(PortHandle,
+                          ObjectAttributes,
+                          MaxConnectInfoLength,
+                          MaxDataLength,
+                          MaxPoolUsage,
+                          FALSE);
 }
 
-/**********************************************************************
- * NAME                                                        EXPORTED
- *     NtCreateWaitablePort/5
- *
- * DESCRIPTION
- *     Waitable ports can be connected to with NtSecureConnectPort.
- *     No port interface can be used with waitable ports but
- *     NtReplyWaitReceivePort and NtReplyWaitReceivePortEx.
- *     Present only in w2k+.
- *
- * ARGUMENTS
- *     PortHandle,
- *     ObjectAttributes,
- *     MaxConnectInfoLength,
- *     MaxDataLength,
- *     MaxPoolUsage
- *
- * RETURN VALUE
+/*
+ * @implemented
  */
-/*EXPORTED*/ NTSTATUS STDCALL
-NtCreateWaitablePort (OUT      PHANDLE                 PortHandle,
-                     IN        POBJECT_ATTRIBUTES      ObjectAttributes,
-                     IN        ULONG                   MaxConnectInfoLength,
-                     IN        ULONG                   MaxDataLength,
-                     IN        ULONG                   MaxPoolUsage)
+NTSTATUS
+NTAPI
+NtCreateWaitablePort(OUT PHANDLE PortHandle,
+                     IN POBJECT_ATTRIBUTES ObjectAttributes,
+                     IN ULONG MaxConnectInfoLength,
+                     IN ULONG MaxDataLength,
+                     IN ULONG MaxPoolUsage)
 {
-  NTSTATUS Status;
-
-  /* Verify parameters */
-  Status = LpcpVerifyCreateParameters (PortHandle,
-                                      ObjectAttributes,
-                                      MaxConnectInfoLength,
-                                      MaxDataLength,
-                                      MaxPoolUsage);
-  if (STATUS_SUCCESS != Status)
-    {
-      return (Status);
-    }
-  /* TODO */
-  return (STATUS_NOT_IMPLEMENTED);
+    PAGED_CODE();
+
+    /* Call the internal API */
+    return LpcpCreatePort(PortHandle,
+                          ObjectAttributes,
+                          MaxConnectInfoLength,
+                          MaxDataLength,
+                          MaxPoolUsage,
+                          TRUE);
 }
 
 /* EOF */
index 901c816..ee2ade0 100644 (file)
@@ -1,72 +1,52 @@
-/* $Id$
- *
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS kernel
+/*
+ * PROJECT:         ReactOS Kernel
+ * LICENSE:         GPL - See COPYING in the top level directory
  * FILE:            ntoskrnl/lpc/listen.c
- * PURPOSE:         Communication mechanism
- *
- * PROGRAMMERS:     David Welch (welch@cwcom.net)
+ * PURPOSE:         Local Procedure Call: Listening
+ * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
  */
 
 /* INCLUDES ******************************************************************/
 
 #include <ntoskrnl.h>
+#include "lpc.h"
 #define NDEBUG
 #include <internal/debug.h>
 
-/* FUNCTIONS *****************************************************************/
+/* PUBLIC FUNCTIONS **********************************************************/
 
-/**********************************************************************
- * NAME                                                        EXPORTED
- *     NtListenPort@8
- *
- * DESCRIPTION
- *     Listen on a named port and wait for a connection attempt.
- *
- * ARGUMENTS
- *     PortHandle      [IN] LPC port to listen on.
- *
- *     ConnectMsg      [IN] User provided storage for a
- *                     possible connection request LPC message.
- *
- * RETURN VALUE
- *     STATUS_SUCCESS if a connection request is received
- *     successfully; otherwise an error code.
- *
- *     The buffer ConnectMessage is filled with the connection
- *     request message queued by NtConnectPort() in PortHandle.
- *
- * NOTE
+/*
+ * @implemented
  */
-/*EXPORTED*/ NTSTATUS STDCALL
-NtListenPort (IN       HANDLE          PortHandle,
-             IN        PPORT_MESSAGE   ConnectMsg)
+NTSTATUS
+NTAPI
+NtListenPort(IN HANDLE PortHandle,
+             OUT PPORT_MESSAGE ConnectMessage)
 {
-  NTSTATUS     Status;
-
-  /*
-   * Wait forever for a connection request.
-   */
-  for (;;)
-    {
-      Status = NtReplyWaitReceivePort(PortHandle,
-                                     NULL,
-                                     NULL,
-                                     ConnectMsg);
-      /*
-       * Accept only LPC_CONNECTION_REQUEST requests.
-       * Drop any other message.
-       */
-      if (!NT_SUCCESS(Status) ||
-         LPC_CONNECTION_REQUEST == ConnectMsg->u2.s2.Type)
-       {
-         DPRINT("Got message (type %x)\n", LPC_CONNECTION_REQUEST);
-         break;
-       }
-      DPRINT("Got message (type %x)\n", ConnectMsg->u2.s2.Type);
-    }
-
-  return (Status);
+        NTSTATUS Status;
+        PAGED_CODE();
+        LPCTRACE(LPC_LISTEN_DEBUG, "Handle: %lx\n", PortHandle);
+
+        /* Wait forever for a connection request. */
+        for (;;)
+        {
+            /* Do the wait */
+            Status = NtReplyWaitReceivePort(PortHandle,
+                                            NULL,
+                                            NULL,
+                                            ConnectMessage);
+
+            /* Accept only LPC_CONNECTION_REQUEST requests. */
+            if ((Status != STATUS_SUCCESS) ||
+                (LpcpGetMessageType(ConnectMessage) == LPC_CONNECTION_REQUEST))
+            {
+                /* Break out */
+                break;
+            }
+        }
+
+        /* Return status */
+        return Status;
 }
 
 
diff --git a/reactos/ntoskrnl/lpc/ntlpc/close.c b/reactos/ntoskrnl/lpc/ntlpc/close.c
deleted file mode 100644 (file)
index af9803d..0000000
+++ /dev/null
@@ -1,395 +0,0 @@
-/*
- * PROJECT:         ReactOS Kernel
- * LICENSE:         GPL - See COPYING in the top level directory
- * FILE:            ntoskrnl/lpc/close.c
- * PURPOSE:         Local Procedure Call: Rundown, Cleanup, Deletion
- * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
- */
-
-/* INCLUDES ******************************************************************/
-
-#include <ntoskrnl.h>
-#include "lpc.h"
-#define NDEBUG
-#include <internal/debug.h>
-
-/* PRIVATE FUNCTIONS *********************************************************/
-
-VOID
-NTAPI
-LpcExitThread(IN PETHREAD Thread)
-{
-    PLPCP_MESSAGE Message;
-
-    /* Acquire the lock */
-    KeAcquireGuardedMutex(&LpcpLock);
-
-    /* Make sure that the Reply Chain is empty */
-    if (!IsListEmpty(&Thread->LpcReplyChain))
-    {
-        /* It's not, remove the entry */
-        RemoveEntryList(&Thread->LpcReplyChain);
-    }
-
-    /* Set the thread in exit mode */
-    Thread->LpcExitThreadCalled = TRUE;
-    Thread->LpcReplyMessageId = 0;
-
-    /* Check if there's a reply message */
-    Message = Thread->LpcReplyMessage;
-    if (Message)
-    {
-        /* FIXME: TODO */
-        KEBUGCHECK(0);
-    }
-
-    /* Release the lock */
-    KeReleaseGuardedMutex(&LpcpLock);
-}
-
-VOID
-NTAPI
-LpcpFreeToPortZone(IN PLPCP_MESSAGE Message,
-                   IN ULONG Flags)
-{
-    PLPCP_CONNECTION_MESSAGE ConnectMessage;
-    PLPCP_PORT_OBJECT ClientPort = NULL;
-    PETHREAD Thread = NULL;
-    BOOLEAN LockHeld = Flags & 1;
-    PAGED_CODE();
-    LPCTRACE(LPC_CLOSE_DEBUG, "Message: %p. Flags: %lx\n", Message, Flags);
-
-    /* Acquire the lock if not already */
-    if (!LockHeld) KeAcquireGuardedMutex(&LpcpLock);
-
-    /* Check if the queue list is empty */
-    if (!IsListEmpty(&Message->Entry))
-    {
-        /* Remove and re-initialize */
-        RemoveEntryList(&Message->Entry);
-        InitializeListHead(&Message->Entry);
-    }
-
-    /* Check if we've already replied */
-    if (Message->RepliedToThread)
-    {
-        /* Set thread to dereference and clean up */
-        Thread = Message->RepliedToThread;
-        Message->RepliedToThread = NULL;
-    }
-
-    /* Check if this is a connection request */
-    if (Message->Request.u2.s2.Type == LPC_CONNECTION_REQUEST)
-    {
-        /* Get the connection message */
-        ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(Message + 1);
-
-        /* Clear the client port */
-        ClientPort = ConnectMessage->ClientPort;
-        if (ClientPort) ConnectMessage->ClientPort = NULL;
-    }
-
-    /* Release the lock */
-    KeReleaseGuardedMutex(&LpcpLock);
-
-    /* Check if we had anything to dereference */
-    if (Thread) ObDereferenceObject(Thread);
-    if (ClientPort) ObDereferenceObject(ClientPort);
-
-    /* Free the entry */
-    ExFreeToPagedLookasideList(&LpcpMessagesLookaside, Message);
-
-    /* Reacquire the lock if needed */
-    if ((LockHeld) && !(Flags & 2)) KeAcquireGuardedMutex(&LpcpLock);
-}
-
-VOID
-NTAPI
-LpcpDestroyPortQueue(IN PLPCP_PORT_OBJECT Port,
-                     IN BOOLEAN Destroy)
-{
-    PLIST_ENTRY ListHead, NextEntry;
-    PETHREAD Thread;
-    PLPCP_MESSAGE Message;
-    PLPCP_CONNECTION_MESSAGE ConnectMessage;
-    LPCTRACE(LPC_CLOSE_DEBUG, "Port: %p. Flags: %lx\n", Port, Port->Flags);
-
-    /* Hold the lock */
-    KeAcquireGuardedMutex(&LpcpLock);
-
-    /* Disconnect the port to which this port is connected */
-    if (Port->ConnectedPort) Port->ConnectedPort->ConnectedPort = NULL;
-
-    /* Check if this is a connection port */
-    if ((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_CONNECTION_PORT)
-    {
-        /* Delete the name */
-        Port->Flags |= LPCP_NAME_DELETED;
-    }
-
-    /* Walk all the threads waiting and signal them */
-    ListHead = &Port->LpcReplyChainHead;
-    NextEntry = ListHead->Flink;
-    while (NextEntry != ListHead)
-    {
-        /* Get the Thread */
-        Thread = CONTAINING_RECORD(NextEntry, ETHREAD, LpcReplyChain);
-
-        /* Make sure we're not in exit */
-        if (Thread->LpcExitThreadCalled) break;
-
-        /* Move to the next entry */
-        NextEntry = NextEntry->Flink;
-
-        /* Remove and reinitialize the List */
-        RemoveEntryList(&Thread->LpcReplyChain);
-        InitializeListHead(&Thread->LpcReplyChain);
-
-        /* Check if someone is waiting */
-        if (!KeReadStateSemaphore(&Thread->LpcReplySemaphore))
-        {
-            /* Get the message and check if it's a connection request */
-            Message = Thread->LpcReplyMessage;
-            if (Message->Request.u2.s2.Type == LPC_CONNECTION_REQUEST)
-            {
-                /* Get the connection message */
-                ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(Message + 1);
-
-                /* Check if it had a section */
-                if (ConnectMessage->SectionToMap)
-                {
-                    /* Dereference it */
-                    ObDereferenceObject(ConnectMessage->SectionToMap);
-                }
-            }
-
-            /* Clear the reply message */
-            Thread->LpcReplyMessage = NULL;
-
-            /* And remove the message from the port zone */
-            LpcpFreeToPortZone(Message, TRUE);
-        }
-
-        /* Release the semaphore and reset message id count */
-        Thread->LpcReplyMessageId = 0;
-        LpcpCompleteWait(&Thread->LpcReplySemaphore);
-    }
-
-    /* Reinitialize the list head */
-    InitializeListHead(&Port->LpcReplyChainHead);
-
-    /* Loop queued messages */
-    ListHead = &Port->MsgQueue.ReceiveHead;
-    NextEntry =  ListHead->Flink;
-    while (ListHead != NextEntry)
-    {
-        /* Get the message */
-        Message = CONTAINING_RECORD(NextEntry, LPCP_MESSAGE, Entry);
-        NextEntry = NextEntry->Flink;
-
-        /* Free and reinitialize it's list head */
-        InitializeListHead(&Message->Entry);
-
-        /* Remove it from the port zone */
-        LpcpFreeToPortZone(Message, TRUE);
-    }
-
-    /* Reinitialize the message queue list head */
-    InitializeListHead(&Port->MsgQueue.ReceiveHead);
-
-    /* Release the lock */
-    KeReleaseGuardedMutex(&LpcpLock);
-
-    /* Check if we have to free the port entirely */
-    if (Destroy)
-    {
-        /* Check if the semaphore exists */
-        if (Port->MsgQueue.Semaphore)
-        {
-            /* Use the semaphore to find the port queue and free it */
-            ExFreePool(CONTAINING_RECORD(Port->MsgQueue.Semaphore,
-                                         LPCP_NONPAGED_PORT_QUEUE,
-                                         Semaphore));
-        }
-    }
-}
-
-VOID
-NTAPI
-LpcpClosePort(IN PEPROCESS Process OPTIONAL,
-              IN PVOID Object,
-              IN ACCESS_MASK GrantedAccess,
-              IN ULONG ProcessHandleCount,
-              IN ULONG SystemHandleCount)
-{
-    PLPCP_PORT_OBJECT Port = (PLPCP_PORT_OBJECT)Object;
-    LPCTRACE(LPC_CLOSE_DEBUG, "Port: %p. Flags: %lx\n", Port, Port->Flags);
-
-    /* Only Server-side Connection Ports need clean up*/
-    if ((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_CONNECTION_PORT)
-    {
-        /* Check the handle count */
-        switch (SystemHandleCount)
-        {
-            /* No handles left */
-            case 0:
-
-                /* Destroy the port queue */
-                LpcpDestroyPortQueue(Port, TRUE);
-                break;
-
-            /* Last handle remaining */
-            case 1:
-
-                /* Reset the queue only */
-                LpcpDestroyPortQueue(Port, FALSE);
-
-            /* More handles remain, do nothing */
-            default:
-                break;
-        }
-    }
-}
-
-VOID
-NTAPI
-LpcpFreePortClientSecurity(IN PLPCP_PORT_OBJECT Port)
-{
-    /* Check if this is a client port */
-    if ((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_CLIENT_PORT)
-    {
-        /* Check if security is static */
-        if (!(Port->Flags & LPCP_SECURITY_DYNAMIC))
-        {
-            /* Check if we have a token */
-            if (Port->StaticSecurity.ClientToken)
-            {
-                /* Free security */
-                SeDeleteClientSecurity(&Port->StaticSecurity);
-            }
-        }
-    }
-}
-
-VOID
-NTAPI
-LpcpDeletePort(IN PVOID ObjectBody)
-{
-    LARGE_INTEGER Timeout;
-    PETHREAD Thread;
-    PLPCP_PORT_OBJECT Port = (PLPCP_PORT_OBJECT)ObjectBody;
-    PLPCP_PORT_OBJECT ConnectionPort;
-    PLPCP_MESSAGE Message;
-    PLIST_ENTRY ListHead, NextEntry;
-    HANDLE Pid;
-    CLIENT_DIED_MSG ClientDiedMsg;
-    Timeout.QuadPart = -1000000;
-    PAGED_CODE();
-    LPCTRACE(LPC_CLOSE_DEBUG, "Port: %p. Flags: %lx\n", Port, Port->Flags);
-
-    /* Check if this is a communication port */
-    if ((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_COMMUNICATION_PORT)
-    {
-        /* Acquire the lock */
-        KeAcquireGuardedMutex(&LpcpLock);
-
-        /* Get the thread */
-        Thread = Port->ClientThread;
-        if (Thread)
-        {
-            /* Clear it */
-            Port->ClientThread = NULL;
-
-            /* Release the lock and dereference */
-            KeReleaseGuardedMutex(&LpcpLock);
-            ObDereferenceObject(Thread);
-        }
-        else
-        {
-            /* Release the lock */
-            KeReleaseGuardedMutex(&LpcpLock);
-        }
-    }
-
-    /* Check if this is a client-side port */
-    if ((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_CLIENT_PORT)
-    {
-        /* Setup the client died message */
-        ClientDiedMsg.h.u1.s1.TotalLength = sizeof(ClientDiedMsg);
-        ClientDiedMsg.h.u1.s1.DataLength = sizeof(ClientDiedMsg.CreateTime);
-        ClientDiedMsg.h.u2.ZeroInit = LPC_PORT_CLOSED;
-        ClientDiedMsg.CreateTime = PsGetCurrentProcess()->CreateTime;
-
-        /* Send it */
-        for (;;)
-        {
-            /* Send the message */
-            if (LpcRequestPort(Port,
-                               &ClientDiedMsg.h) != STATUS_NO_MEMORY) break;
-
-            /* Wait until trying again */
-            KeDelayExecutionThread(KernelMode, FALSE, &Timeout);
-        }
-    }
-
-    /* Destroy the port queue */
-    LpcpDestroyPortQueue(Port, TRUE);
-
-    /* Check if we had a client view */
-    if (Port->ClientSectionBase) MmUnmapViewOfSection(PsGetCurrentProcess(),
-                                                      Port->ClientSectionBase);
-
-    /* Check for a server view */
-    if (Port->ServerSectionBase) MmUnmapViewOfSection(PsGetCurrentProcess(),
-                                                      Port->ServerSectionBase);
-
-    /* Get the connection port */
-    ConnectionPort = Port->ConnectionPort;
-    if (ConnectionPort)
-    {
-        /* Get the PID */
-        Pid = PsGetCurrentProcessId();
-
-        /* Acquire the lock */
-        KeAcquireGuardedMutex(&LpcpLock);
-
-        /* Loop the data lists */
-        ListHead = &ConnectionPort->LpcDataInfoChainHead;
-        NextEntry = ListHead->Flink;
-        while (NextEntry != ListHead)
-        {
-            /* Get the message */
-            Message = CONTAINING_RECORD(NextEntry, LPCP_MESSAGE, Entry);
-            NextEntry = NextEntry->Flink;
-
-            /* Check if the PID matches */
-            if (Message->Request.ClientId.UniqueProcess == Pid)
-            {
-                /* Remove it */
-                RemoveEntryList(&Message->Entry);
-                LpcpFreeToPortZone(Message, TRUE);
-            }
-        }
-
-        /* Release the lock */
-        KeReleaseGuardedMutex(&LpcpLock);
-
-        /* Dereference the object unless it's the same port */
-        if (ConnectionPort != Port) ObDereferenceObject(ConnectionPort);
-    }
-
-    /* Check if this is a connection port with a server process*/
-    if (((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_CONNECTION_PORT) &&
-        (ConnectionPort->ServerProcess))
-    {
-        /* Dereference the server process */
-        ObDereferenceObject(ConnectionPort->ServerProcess);
-        ConnectionPort->ServerProcess = NULL;
-    }
-
-    /* Free client security */
-    LpcpFreePortClientSecurity(Port);
-    LPCTRACE(LPC_CLOSE_DEBUG, "Port: %p deleted\n", Port);
-}
-
-/* EOF */
diff --git a/reactos/ntoskrnl/lpc/ntlpc/complete.c b/reactos/ntoskrnl/lpc/ntlpc/complete.c
deleted file mode 100644 (file)
index b5e4e19..0000000
+++ /dev/null
@@ -1,376 +0,0 @@
-/*
-* PROJECT:         ReactOS Kernel
-* LICENSE:         GPL - See COPYING in the top level directory
-* FILE:            ntoskrnl/lpc/complete.c
-* PURPOSE:         Local Procedure Call: Connection Completion
-* PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
-*/
-
-/* INCLUDES ******************************************************************/
-
-#include <ntoskrnl.h>
-#include "lpc.h"
-#define NDEBUG
-#include <internal/debug.h>
-
-/* PRIVATE FUNCTIONS *********************************************************/
-
-VOID
-NTAPI
-LpcpPrepareToWakeClient(IN PETHREAD Thread)
-{
-    PAGED_CODE();
-
-    /* Make sure the thread isn't dying and it has a valid chain */
-    if (!(Thread->LpcExitThreadCalled) &&
-        !(IsListEmpty(&Thread->LpcReplyChain)))
-    {
-        /* Remove it from the list and reinitialize it */
-        RemoveEntryList(&Thread->LpcReplyChain);
-        InitializeListHead(&Thread->LpcReplyChain);
-    }
-}
-
-/* PUBLIC FUNCTIONS **********************************************************/
-
-/*
- * @implemented
- */
-NTSTATUS
-NTAPI
-NtAcceptConnectPort(OUT PHANDLE PortHandle,
-                    IN PVOID PortContext OPTIONAL,
-                    IN PPORT_MESSAGE ReplyMessage,
-                    IN BOOLEAN AcceptConnection,
-                    IN PPORT_VIEW ServerView,
-                    IN PREMOTE_PORT_VIEW ClientView)
-{
-    PLPCP_PORT_OBJECT ConnectionPort, ServerPort, ClientPort;
-    PVOID ClientSectionToMap = NULL;
-    HANDLE Handle;
-    KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
-    NTSTATUS Status;
-    ULONG ConnectionInfoLength;
-    PLPCP_MESSAGE Message;
-    PLPCP_CONNECTION_MESSAGE ConnectMessage;
-    PEPROCESS ClientProcess;
-    PETHREAD ClientThread;
-    LARGE_INTEGER SectionOffset;
-    PAGED_CODE();
-    LPCTRACE(LPC_COMPLETE_DEBUG,
-             "Context: %p. Message: %p. Accept: %lx. Views: %p/%p\n",
-             PortContext,
-             ReplyMessage,
-             AcceptConnection,
-             ClientView,
-             ServerView);
-
-    /* Validate the size of the server view */
-    if ((ServerView) && (ServerView->Length != sizeof(PORT_VIEW)))
-    {
-        /* Invalid size */
-        return STATUS_INVALID_PARAMETER;
-    }
-
-    /* Validate the size of the client view */
-    if ((ClientView) && (ClientView->Length != sizeof(REMOTE_PORT_VIEW)))
-    {
-        /* Invalid size */
-        return STATUS_INVALID_PARAMETER;
-    }
-
-    /* Get the client process and thread */
-    Status = PsLookupProcessThreadByCid(&ReplyMessage->ClientId,
-                                        &ClientProcess,
-                                        &ClientThread);
-    if (!NT_SUCCESS(Status)) return Status;
-
-    /* Acquire the LPC Lock */
-    KeAcquireGuardedMutex(&LpcpLock);
-
-    /* Make sure that the client wants a reply, and this is the right one */
-    if (!(ClientThread->LpcReplyMessage) ||
-        !(ReplyMessage->MessageId) ||
-        (ClientThread->LpcReplyMessageId != ReplyMessage->MessageId))
-    {
-        /* Not the reply asked for, or no reply wanted, fail */
-        KeReleaseGuardedMutex(&LpcpLock);
-        ObDereferenceObject(ClientProcess);
-        ObDereferenceObject(ClientThread);
-        return STATUS_REPLY_MESSAGE_MISMATCH;
-    }
-
-    /* Now get the message and connection message */
-    Message = ClientThread->LpcReplyMessage;
-    ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(Message + 1);
-
-    /* Get the client and connection port as well */
-    ClientPort = ConnectMessage->ClientPort;
-    ConnectionPort = ClientPort->ConnectionPort;
-
-    /* Make sure that the reply is being sent to the proper server process */
-    if (ConnectionPort->ServerProcess != PsGetCurrentProcess())
-    {
-        /* It's not, so fail */
-        KeReleaseGuardedMutex(&LpcpLock);
-        ObDereferenceObject(ClientProcess);
-        ObDereferenceObject(ClientThread);
-        return STATUS_REPLY_MESSAGE_MISMATCH;
-    }
-
-    /* At this point, don't let other accept attempts happen */
-    ClientThread->LpcReplyMessage = NULL;
-    ClientThread->LpcReplyMessageId = 0;
-
-    /* Clear the client port for now as well, then release the lock */
-    ConnectMessage->ClientPort = NULL;
-    KeReleaseGuardedMutex(&LpcpLock);
-
-    /* Get the connection information length */
-    ConnectionInfoLength = ReplyMessage->u1.s1.DataLength;
-    if (ConnectionInfoLength > ConnectionPort->MaxConnectionInfoLength)
-    {
-        /* Normalize it since it's too large */
-        ConnectionInfoLength = ConnectionPort->MaxConnectionInfoLength;
-    }
-
-    /* Set the sizes of our reply message */
-    Message->Request.u1.s1.DataLength = sizeof(LPCP_CONNECTION_MESSAGE) +
-                                    ConnectionInfoLength;
-    Message->Request.u1.s1.TotalLength = sizeof(LPCP_MESSAGE) +
-                                     Message->Request.u1.s1.DataLength;
-
-    /* Setup the reply message */
-    Message->Request.u2.s2.Type = LPC_REPLY;
-    Message->Request.u2.s2.DataInfoOffset = 0;
-    Message->Request.ClientId = ReplyMessage->ClientId;
-    Message->Request.MessageId = ReplyMessage->MessageId;
-    Message->Request.ClientViewSize = 0;
-    RtlMoveMemory(ConnectMessage + 1, ReplyMessage + 1, ConnectionInfoLength);
-
-    /* At this point, if the caller refused the connection, go to cleanup */
-    if (!AcceptConnection) goto Cleanup;
-
-    /* Otherwise, create the actual port */
-    Status = ObCreateObject(PreviousMode,
-                            LpcPortObjectType,
-                            NULL,
-                            PreviousMode,
-                            NULL,
-                            sizeof(LPCP_PORT_OBJECT),
-                            0,
-                            0,
-                            (PVOID*)&ServerPort);
-    if (!NT_SUCCESS(Status)) goto Cleanup;
-
-    /* Set it up */
-    RtlZeroMemory(ServerPort, sizeof(LPCP_PORT_OBJECT));
-    ServerPort->PortContext = PortContext;
-    ServerPort->Flags = LPCP_COMMUNICATION_PORT;
-    ServerPort->MaxMessageLength = ConnectionPort->MaxMessageLength;
-    InitializeListHead(&ServerPort->LpcReplyChainHead);
-    InitializeListHead(&ServerPort->LpcDataInfoChainHead);
-
-    /* Reference the connection port until we're fully setup */
-    ObReferenceObject(ConnectionPort);
-
-    /* Link the ports together */
-    ServerPort->ConnectionPort = ConnectionPort;
-    ServerPort->ConnectedPort = ClientPort;
-    ClientPort->ConnectedPort = ServerPort;
-
-    /* Also set the creator CID */
-    ServerPort->Creator = PsGetCurrentThread()->Cid;
-    ClientPort->Creator = Message->Request.ClientId;
-
-    /* Get the section associated and then clear it, while inside the lock */
-    KeAcquireGuardedMutex(&LpcpLock);
-    ClientSectionToMap = ConnectMessage->SectionToMap;
-    ConnectMessage->SectionToMap = NULL;
-    KeReleaseGuardedMutex(&LpcpLock);
-
-    /* Now check if there's a client section */
-    if (ClientSectionToMap)
-    {
-        /* Setup the offset */
-        SectionOffset.QuadPart = ConnectMessage->ClientView.SectionOffset;
-
-        /* Map the section */
-        Status = MmMapViewOfSection(ClientSectionToMap,
-                                    PsGetCurrentProcess(),
-                                    &ServerPort->ClientSectionBase,
-                                    0,
-                                    0,
-                                    &SectionOffset,
-                                    &ConnectMessage->ClientView.ViewSize,
-                                    ViewUnmap,
-                                    0,
-                                    PAGE_READWRITE);
-
-        /* Update the offset and check for mapping status */
-        ConnectMessage->ClientView.SectionOffset = SectionOffset.LowPart;
-        if (NT_SUCCESS(Status))
-        {
-            /* Set the view base */
-            ConnectMessage->ClientView.ViewRemoteBase = ServerPort->
-                                                        ClientSectionBase;
-        }
-        else
-        {
-            /* Otherwise, quit */
-            ObDereferenceObject(ServerPort);
-            goto Cleanup;
-        }
-    }
-
-    /* Check if there's a server section */
-    if (ServerView)
-    {
-        /* FIXME: TODO */
-        ASSERT(FALSE);
-    }
-
-    /* Reference the server port until it's fully inserted */
-    ObReferenceObject(ServerPort);
-
-    /* Insert the server port in the namespace */
-    Status = ObInsertObject(ServerPort,
-                            NULL,
-                            PORT_ALL_ACCESS,
-                            0,
-                            NULL,
-                            &Handle);
-    if (!NT_SUCCESS(Status))
-    {
-        /* We failed, remove the extra reference and cleanup */
-        ObDereferenceObject(ServerPort);
-        goto Cleanup;
-    }
-
-    /* Check if the caller gave a client view */
-    if (ClientView)
-    {
-        /* Fill it out */
-        ClientView->ViewBase = ConnectMessage->ClientView.ViewRemoteBase;
-        ClientView->ViewSize = ConnectMessage->ClientView.ViewSize;
-    }
-
-    /* Return the handle to user mode */
-    *PortHandle = Handle;
-    LPCTRACE(LPC_COMPLETE_DEBUG,
-             "Handle: %lx. Messages: %p/%p. Ports: %p/%p/%p\n",
-             Handle,
-             Message,
-             ConnectMessage,
-             ServerPort,
-             ClientPort,
-             ConnectionPort);
-
-    /* If there was no port context, use the handle by default */
-    if (!PortContext) ServerPort->PortContext = Handle;
-    ServerPort->ClientThread = ClientThread;
-
-    /* Set this message as the LPC Reply message while holding the lock */
-    KeAcquireGuardedMutex(&LpcpLock);
-    ClientThread->LpcReplyMessage = Message;
-    KeReleaseGuardedMutex(&LpcpLock);
-
-    /* Clear the thread pointer so it doesn't get cleaned later */
-    ClientThread = NULL;
-
-    /* Remove the extra reference we had added */
-    ObDereferenceObject(ServerPort);
-
-Cleanup:
-    /* If there was a section, dereference it */
-    if (ClientSectionToMap) ObDereferenceObject(ClientSectionToMap);
-
-    /* Check if we got here while still having a client thread */
-    if (ClientThread)
-    {
-        /* FIXME: Complex cleanup code */
-        ASSERT(FALSE);
-    }
-
-    /* Dereference the client port if we have one, and the process */
-    LPCTRACE(LPC_COMPLETE_DEBUG,
-             "Status: %lx. Thread: %p. Process: [%.16s]\n",
-             Status,
-             ClientThread,
-             ClientProcess->ImageFileName);
-    if (ClientPort) ObDereferenceObject(ClientPort);
-    ObDereferenceObject(ClientProcess);
-    return Status;
-}
-
-/*
- * @implemented
- */
-NTSTATUS
-NTAPI
-NtCompleteConnectPort(IN HANDLE PortHandle)
-{
-    NTSTATUS Status;
-    PLPCP_PORT_OBJECT Port;
-    KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
-    PETHREAD Thread;
-    PAGED_CODE();
-    LPCTRACE(LPC_COMPLETE_DEBUG, "Handle: %lx\n", PortHandle);
-
-    /* Get the Port Object */
-    Status = ObReferenceObjectByHandle(PortHandle,
-                                       PORT_ALL_ACCESS,
-                                       LpcPortObjectType,
-                                       PreviousMode,
-                                       (PVOID*)&Port,
-                                       NULL);
-    if (!NT_SUCCESS(Status)) return Status;
-
-    /* Make sure this is a connection port */
-    if ((Port->Flags & LPCP_PORT_TYPE_MASK) != LPCP_COMMUNICATION_PORT)
-    {
-        /* It isn't, fail */
-        ObDereferenceObject(Port);
-        return STATUS_INVALID_PORT_HANDLE;
-    }
-
-    /* Acquire the lock */
-    KeAcquireGuardedMutex(&LpcpLock);
-
-    /* Make sure we have a client thread */
-    if (!Port->ClientThread)
-    {
-        /* We don't, fail */
-        KeReleaseGuardedMutex(&LpcpLock);
-        ObDereferenceObject(Port);
-        return STATUS_INVALID_PARAMETER;
-    }
-
-    /* Get the thread */
-    Thread = Port->ClientThread;
-
-    /* Make sure it has a reply message */
-    if (!Thread->LpcReplyMessage)
-    {
-        /* It doesn't, fail */
-        KeReleaseGuardedMutex(&LpcpLock);
-        ObDereferenceObject(Port);
-        return STATUS_PORT_DISCONNECTED;
-    }
-
-    /* Clear the client thread and wake it up */
-    Port->ClientThread = NULL;
-    LpcpPrepareToWakeClient(Thread);
-
-    /* Release the lock and wait for an answer */
-    KeReleaseGuardedMutex(&LpcpLock);
-    LpcpCompleteWait(&Thread->LpcReplySemaphore);
-
-    /* Dereference the Thread and Port  and return */
-    ObDereferenceObject(Port);
-    ObDereferenceObject(Thread);
-    LPCTRACE(LPC_COMPLETE_DEBUG, "Port: %p. Thread: %p\n", Port, Thread);
-    return Status;
-}
-
-/* EOF */
diff --git a/reactos/ntoskrnl/lpc/ntlpc/connect.c b/reactos/ntoskrnl/lpc/ntlpc/connect.c
deleted file mode 100644 (file)
index 2b9259e..0000000
+++ /dev/null
@@ -1,568 +0,0 @@
-/*
- * PROJECT:         ReactOS Kernel
- * LICENSE:         GPL - See COPYING in the top level directory
- * FILE:            ntoskrnl/lpc/connect.c
- * PURPOSE:         Local Procedure Call: Connection Management
- * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
- */
-
-/* INCLUDES ******************************************************************/
-
-#include <ntoskrnl.h>
-#include "lpc.h"
-#define NDEBUG
-#include <internal/debug.h>
-
-/* PRIVATE FUNCTIONS *********************************************************/
-
-PVOID
-NTAPI
-LpcpFreeConMsg(IN OUT PLPCP_MESSAGE *Message,
-               IN OUT PLPCP_CONNECTION_MESSAGE *ConnectMessage,
-               IN PETHREAD CurrentThread)
-{
-    PVOID SectionToMap;
-
-    /* Acquire the LPC lock */
-    KeAcquireGuardedMutex(&LpcpLock);
-
-    /* Check if the reply chain is not empty */
-    if (!IsListEmpty(&CurrentThread->LpcReplyChain))
-    {
-        /* Remove this entry and re-initialize it */
-        RemoveEntryList(&CurrentThread->LpcReplyChain);
-        InitializeListHead(&CurrentThread->LpcReplyChain);
-    }
-
-    /* Check if there's a reply message */
-    if (CurrentThread->LpcReplyMessage)
-    {
-        /* Get the message */
-        *Message = CurrentThread->LpcReplyMessage;
-
-        /* Clear message data */
-        CurrentThread->LpcReceivedMessageId = 0;
-        CurrentThread->LpcReplyMessage = NULL;
-
-        /* Get the connection message and clear the section */
-        *ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(*Message + 1);
-        SectionToMap = (*ConnectMessage)->SectionToMap;
-        (*ConnectMessage)->SectionToMap = NULL;
-    }
-    else
-    {
-        /* No message to return */
-        *Message = NULL;
-        SectionToMap = NULL;
-    }
-
-    /* Release the lock and return the section */
-    KeReleaseGuardedMutex(&LpcpLock);
-    return SectionToMap;
-}
-
-/* PUBLIC FUNCTIONS **********************************************************/
-
-/*
- * @implemented
- */
-NTSTATUS
-NTAPI
-NtSecureConnectPort(OUT PHANDLE PortHandle,
-                    IN PUNICODE_STRING PortName,
-                    IN PSECURITY_QUALITY_OF_SERVICE Qos,
-                    IN OUT PPORT_VIEW ClientView OPTIONAL,
-                    IN PSID ServerSid OPTIONAL,
-                    IN OUT PREMOTE_PORT_VIEW ServerView OPTIONAL,
-                    OUT PULONG MaxMessageLength OPTIONAL,
-                    IN OUT PVOID ConnectionInformation OPTIONAL,
-                    IN OUT PULONG ConnectionInformationLength OPTIONAL)
-{
-    ULONG ConnectionInfoLength = 0;
-    PLPCP_PORT_OBJECT Port, ClientPort;
-    KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
-    NTSTATUS Status = STATUS_SUCCESS;
-    HANDLE Handle;
-    PVOID SectionToMap;
-    PLPCP_MESSAGE Message;
-    PLPCP_CONNECTION_MESSAGE ConnectMessage;
-    PETHREAD Thread = PsGetCurrentThread();
-    ULONG PortMessageLength;
-    LARGE_INTEGER SectionOffset;
-    PTOKEN Token;
-    PTOKEN_USER TokenUserInfo;
-    PAGED_CODE();
-    LPCTRACE(LPC_CONNECT_DEBUG,
-             "Name: %wZ. Qos: %p. Views: %p/%p. Sid: %p\n",
-             PortName,
-             Qos,
-             ClientView,
-             ServerView,
-             ServerSid);
-
-    /* Validate client view */
-    if ((ClientView) && (ClientView->Length != sizeof(PORT_VIEW)))
-    {
-        /* Fail */
-        return STATUS_INVALID_PARAMETER;
-    }
-
-    /* Validate server view */
-    if ((ServerView) && (ServerView->Length != sizeof(REMOTE_PORT_VIEW)))
-    {
-        /* Fail */
-        return STATUS_INVALID_PARAMETER;
-    }
-
-    /* Check if caller sent connection information length */
-    if (ConnectionInformationLength)
-    {
-        /* Retrieve the input length */
-        ConnectionInfoLength = *ConnectionInformationLength;
-    }
-
-    /* Get the port */
-    Status = ObReferenceObjectByName(PortName,
-                                     0,
-                                     NULL,
-                                     PORT_ALL_ACCESS,
-                                     LpcPortObjectType,
-                                     PreviousMode,
-                                     NULL,
-                                     (PVOID *)&Port);
-    if (!NT_SUCCESS(Status)) return Status;
-
-    /* This has to be a connection port */
-    if ((Port->Flags & LPCP_PORT_TYPE_MASK) != LPCP_CONNECTION_PORT)
-    {
-        /* It isn't, so fail */
-        ObDereferenceObject(Port);
-        return STATUS_INVALID_PORT_HANDLE;
-    }
-
-    /* Check if we have a SID */
-    if (ServerSid)
-    {
-        /* Make sure that we have a server */
-        if (Port->ServerProcess)
-        {
-            /* Get its token and query user information */
-            Token = PsReferencePrimaryToken(Port->ServerProcess);
-            //Status = SeQueryInformationToken(Token, TokenUser, (PVOID*)&TokenUserInfo);
-            // FIXME: Need SeQueryInformationToken
-            Status = STATUS_SUCCESS;
-            TokenUserInfo = ExAllocatePool(PagedPool, sizeof(TOKEN_USER));
-            TokenUserInfo->User.Sid = ServerSid;
-            PsDereferencePrimaryToken(Token);
-
-            /* Check for success */
-            if (NT_SUCCESS(Status))
-            {
-                /* Compare the SIDs */
-                if (!RtlEqualSid(ServerSid, TokenUserInfo->User.Sid))
-                {
-                    /* Fail */
-                    Status = STATUS_SERVER_SID_MISMATCH;
-                }
-
-                /* Free token information */
-                ExFreePool(TokenUserInfo);
-            }
-        }
-        else
-        {
-            /* Invalid SID */
-            Status = STATUS_SERVER_SID_MISMATCH;
-        }
-
-        /* Check if SID failed */
-        if (!NT_SUCCESS(Status))
-        {
-            /* Quit */
-            ObDereferenceObject(Port);
-            return Status;
-        }
-    }
-
-    /* Create the client port */
-    Status = ObCreateObject(PreviousMode,
-                            LpcPortObjectType,
-                            NULL,
-                            PreviousMode,
-                            NULL,
-                            sizeof(LPCP_PORT_OBJECT),
-                            0,
-                            0,
-                            (PVOID *)&ClientPort);
-    if (!NT_SUCCESS(Status))
-    {
-        /* Failed, dereference the server port and return */
-        ObDereferenceObject(Port);
-        return Status;
-    }
-
-    /* Setup the client port */
-    RtlZeroMemory(ClientPort, sizeof(LPCP_PORT_OBJECT));
-    ClientPort->Flags = LPCP_CLIENT_PORT;
-    ClientPort->ConnectionPort = Port;
-    ClientPort->MaxMessageLength = Port->MaxMessageLength;
-    ClientPort->SecurityQos = *Qos;
-    InitializeListHead(&ClientPort->LpcReplyChainHead);
-    InitializeListHead(&ClientPort->LpcDataInfoChainHead);
-
-    /* Check if we have dynamic security */
-    if (Qos->ContextTrackingMode == SECURITY_DYNAMIC_TRACKING)
-    {
-        /* Remember that */
-        ClientPort->Flags |= LPCP_SECURITY_DYNAMIC;
-    }
-    else
-    {
-        /* Create our own client security */
-        Status = SeCreateClientSecurity(Thread,
-                                        Qos,
-                                        FALSE,
-                                        &ClientPort->StaticSecurity);
-        if (!NT_SUCCESS(Status))
-        {
-            /* Security failed, dereference and return */
-            ObDereferenceObject(ClientPort);
-            return Status;
-        }
-    }
-
-    /* Initialize the port queue */
-    Status = LpcpInitializePortQueue(ClientPort);
-    if (!NT_SUCCESS(Status))
-    {
-        /* Failed */
-        ObDereferenceObject(ClientPort);
-        return Status;
-    }
-
-    /* Check if we have a client view */
-    if (ClientView)
-    {
-        /* Get the section handle */
-        Status = ObReferenceObjectByHandle(ClientView->SectionHandle,
-                                           SECTION_MAP_READ |
-                                           SECTION_MAP_WRITE,
-                                           MmSectionObjectType,
-                                           PreviousMode,
-                                           (PVOID*)&SectionToMap,
-                                           NULL);
-        if (!NT_SUCCESS(Status))
-        {
-            /* Fail */
-            ObDereferenceObject(Port);
-            return Status;
-        }
-
-        /* Set the section offset */
-        SectionOffset.QuadPart = ClientView->SectionOffset;
-
-        /* Map it */
-        Status = MmMapViewOfSection(SectionToMap,
-                                    PsGetCurrentProcess(),
-                                    &Port->ClientSectionBase,
-                                    0,
-                                    0,
-                                    &SectionOffset,
-                                    &ClientView->ViewSize,
-                                    ViewUnmap,
-                                    0,
-                                    PAGE_READWRITE);
-
-        /* Update the offset */
-        ClientView->SectionOffset = SectionOffset.LowPart;
-
-        /* Check for failure */
-        if (!NT_SUCCESS(Status))
-        {
-            /* Fail */
-            ObDereferenceObject(SectionToMap);
-            ObDereferenceObject(Port);
-            return Status;
-        }
-
-        /* Update the base */
-        ClientView->ViewBase = Port->ClientSectionBase;
-    }
-    else
-    {
-        /* No section */
-        SectionToMap = NULL;
-    }
-
-    /* Normalize connection information */
-    if (ConnectionInfoLength > Port->MaxConnectionInfoLength)
-    {
-        /* Use the port's maximum allowed value */
-        ConnectionInfoLength = Port->MaxConnectionInfoLength;
-    }
-
-    /* Allocate a message from the port zone */
-    Message = LpcpAllocateFromPortZone();
-    if (!Message)
-    {
-        /* Fail if we couldn't allocate a message */
-        if (SectionToMap) ObDereferenceObject(SectionToMap);
-        ObDereferenceObject(ClientPort);
-        return STATUS_NO_MEMORY;
-    }
-
-    /* Set pointer to the connection message and fill in the CID */
-    ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(Message + 1);
-    Message->Request.ClientId = Thread->Cid;
-
-    /* Check if we have a client view */
-    if (ClientView)
-    {
-        /* Set the view size */
-        Message->Request.ClientViewSize = ClientView->ViewSize;
-
-        /* Copy the client view and clear the server view */
-        RtlMoveMemory(&ConnectMessage->ClientView,
-                      ClientView,
-                      sizeof(PORT_VIEW));
-        RtlZeroMemory(&ConnectMessage->ServerView, sizeof(REMOTE_PORT_VIEW));
-    }
-    else
-    {
-        /* Set the size to 0 and clear the connect message */
-        Message->Request.ClientViewSize = 0;
-        RtlZeroMemory(ConnectMessage, sizeof(LPCP_CONNECTION_MESSAGE));
-    }
-
-    /* Set the section and client port. Port is NULL for now */
-    ConnectMessage->ClientPort = NULL;
-    ConnectMessage->SectionToMap = SectionToMap;
-
-    /* Set the data for the connection request message */
-    Message->Request.u1.s1.DataLength = sizeof(LPCP_CONNECTION_MESSAGE) +
-                                        ConnectionInfoLength;
-    Message->Request.u1.s1.TotalLength = sizeof(LPCP_MESSAGE) +
-                                         Message->Request.u1.s1.DataLength;
-    Message->Request.u2.s2.Type = LPC_CONNECTION_REQUEST;
-
-    /* Check if we have connection information */
-    if (ConnectionInformation)
-    {
-        /* Copy it in */
-        RtlMoveMemory(ConnectMessage + 1,
-                      ConnectionInformation,
-                      ConnectionInfoLength);
-    }
-
-    /* Acquire the port lock */
-    KeAcquireGuardedMutex(&LpcpLock);
-
-    /* Check if someone already deleted the port name */
-    if (Port->Flags & LPCP_NAME_DELETED)
-    {
-        /* Fail the request */
-        KeReleaseGuardedMutex(&LpcpLock);
-        Status = STATUS_OBJECT_NAME_NOT_FOUND;
-        goto Cleanup;
-    }
-
-    /* Associate no thread yet */
-    Message->RepliedToThread = NULL;
-
-    /* Generate the Message ID and set it */
-    Message->Request.MessageId =  LpcpNextMessageId++;
-    if (!LpcpNextMessageId) LpcpNextMessageId = 1;
-    Thread->LpcReplyMessageId = Message->Request.MessageId;
-
-    /* Insert the message into the queue and thread chain */
-    InsertTailList(&Port->MsgQueue.ReceiveHead, &Message->Entry);
-    InsertTailList(&Port->LpcReplyChainHead, &Thread->LpcReplyChain);
-    Thread->LpcReplyMessage = Message;
-
-    /* Now we can finally reference the client port and link it*/
-    ObReferenceObject(ClientPort);
-    ConnectMessage->ClientPort = ClientPort;
-
-    /* Release the lock */
-    KeReleaseGuardedMutex(&LpcpLock);
-    LPCTRACE(LPC_CONNECT_DEBUG,
-             "Messages: %p/%p. Ports: %p/%p. Status: %lx\n",
-             Message,
-             ConnectMessage,
-             Port,
-             ClientPort,
-             Status);
-
-    /* If this is a waitable port, set the event */
-    if (Port->Flags & LPCP_WAITABLE_PORT) KeSetEvent(&Port->WaitEvent,
-                                                     1,
-                                                     FALSE);
-
-    /* Release the queue semaphore */
-    LpcpCompleteWait(Port->MsgQueue.Semaphore);
-
-    /* Now wait for a reply */
-    LpcpConnectWait(&Thread->LpcReplySemaphore, PreviousMode);
-
-    /* Check if our wait ended in success */
-    if (Status != STATUS_SUCCESS) goto Cleanup;
-
-    /* Free the connection message */
-    SectionToMap = LpcpFreeConMsg(&Message, &ConnectMessage, Thread);
-
-    /* Check if we got a message back */
-    if (Message)
-    {
-        /* Check for new return length */
-        if ((Message->Request.u1.s1.DataLength -
-             sizeof(LPCP_CONNECTION_MESSAGE)) < ConnectionInfoLength)
-        {
-            /* Set new normalized connection length */
-            ConnectionInfoLength = Message->Request.u1.s1.DataLength -
-                                   sizeof(LPCP_CONNECTION_MESSAGE);
-        }
-
-        /* Check if we had connection information */
-        if (ConnectionInformation)
-        {
-            /* Check if we had a length pointer */
-            if (ConnectionInformationLength)
-            {
-                /* Return the length */
-                *ConnectionInformationLength = ConnectionInfoLength;
-            }
-
-            /* Return the connection information */
-            RtlMoveMemory(ConnectionInformation,
-                          ConnectMessage + 1,
-                          ConnectionInfoLength );
-        }
-
-        /* Make sure we had a connected port */
-        if (ClientPort->ConnectedPort)
-        {
-            /* Get the message length before the port might get killed */
-            PortMessageLength = Port->MaxMessageLength;
-
-            /* Insert the client port */
-            Status = ObInsertObject(ClientPort,
-                                    NULL,
-                                    PORT_ALL_ACCESS,
-                                    0,
-                                    (PVOID *)NULL,
-                                    &Handle);
-            if (NT_SUCCESS(Status))
-            {
-                /* Return the handle */
-                *PortHandle = Handle;
-                LPCTRACE(LPC_CONNECT_DEBUG,
-                         "Handle: %lx. Length: %lx\n",
-                         Handle,
-                         PortMessageLength);
-
-                /* Check if maximum length was requested */
-                if (MaxMessageLength) *MaxMessageLength = PortMessageLength;
-
-                /* Check if we had a client view */
-                if (ClientView)
-                {
-                    /* Copy it back */
-                    RtlMoveMemory(ClientView,
-                                  &ConnectMessage->ClientView,
-                                  sizeof(PORT_VIEW));
-                }
-
-                /* Check if we had a server view */
-                if (ServerView)
-                {
-                    /* Copy it back */
-                    RtlMoveMemory(ServerView,
-                                  &ConnectMessage->ServerView,
-                                  sizeof(REMOTE_PORT_VIEW));
-                }
-            }
-        }
-        else
-        {
-            /* No connection port, we failed */
-            if (SectionToMap) ObDereferenceObject(SectionToMap);
-
-            /* Check if it's because the name got deleted */
-            if (Port->Flags & LPCP_NAME_DELETED)
-            {
-                /* Set the correct status */
-                Status = STATUS_OBJECT_NAME_NOT_FOUND;
-            }
-            else
-            {
-                /* Otherwise, the caller refused us */
-                Status = STATUS_PORT_CONNECTION_REFUSED;
-            }
-
-            /* Kill the port */
-            ObDereferenceObject(ClientPort);
-        }
-
-        /* Free the message */
-        LpcpFreeToPortZone(Message, FALSE);
-        return Status;
-    }
-
-    /* No reply message, fail */
-    if (SectionToMap) ObDereferenceObject(SectionToMap);
-    ObDereferenceObject(ClientPort);
-    return STATUS_PORT_CONNECTION_REFUSED;
-
-Cleanup:
-    /* We failed, free the message */
-    SectionToMap = LpcpFreeConMsg(&Message, &ConnectMessage, Thread);
-
-    /* Check if the semaphore got signaled */
-    if (KeReadStateSemaphore(&Thread->LpcReplySemaphore))
-    {
-        /* Wait on it */
-        KeWaitForSingleObject(&Thread->LpcReplySemaphore,
-                              KernelMode,
-                              Executive,
-                              FALSE,
-                              NULL);
-    }
-
-    /* Check if we had a message and free it */
-    if (Message) LpcpFreeToPortZone(Message, FALSE);
-
-    /* Dereference other objects */
-    if (SectionToMap) ObDereferenceObject(SectionToMap);
-    ObDereferenceObject(ClientPort);
-
-    /* Return status */
-    return Status;
-}
-
-/*
- * @implemented
- */
-NTSTATUS
-NTAPI
-NtConnectPort(OUT PHANDLE PortHandle,
-              IN PUNICODE_STRING PortName,
-              IN PSECURITY_QUALITY_OF_SERVICE Qos,
-              IN PPORT_VIEW ClientView,
-              IN PREMOTE_PORT_VIEW ServerView,
-              OUT PULONG MaxMessageLength,
-              IN PVOID ConnectionInformation,
-              OUT PULONG ConnectionInformationLength)
-{
-    /* Call the newer API */
-    return NtSecureConnectPort(PortHandle,
-                               PortName,
-                               Qos,
-                               ClientView,
-                               NULL,
-                               ServerView,
-                               MaxMessageLength,
-                               ConnectionInformation,
-                               ConnectionInformationLength);
-}
-
-/* EOF */
diff --git a/reactos/ntoskrnl/lpc/ntlpc/create.c b/reactos/ntoskrnl/lpc/ntlpc/create.c
deleted file mode 100644 (file)
index 2bf08c1..0000000
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * PROJECT:         ReactOS Kernel
- * LICENSE:         GPL - See COPYING in the top level directory
- * FILE:            ntoskrnl/lpc/create.c
- * PURPOSE:         Local Procedure Call: Port/Queue/Message Creation
- * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
- */
-
-/* INCLUDES ******************************************************************/
-
-#include <ntoskrnl.h>
-#include "lpc.h"
-#define NDEBUG
-#include <internal/debug.h>
-
-/* PRIVATE FUNCTIONS *********************************************************/
-
-NTSTATUS
-NTAPI
-LpcpInitializePortQueue(IN PLPCP_PORT_OBJECT Port)
-{
-    PLPCP_NONPAGED_PORT_QUEUE MessageQueue;
-
-    /* Allocate the queue */
-    MessageQueue = ExAllocatePoolWithTag(NonPagedPool,
-                                         sizeof(LPCP_NONPAGED_PORT_QUEUE),
-                                         TAG('P', 'o', 'r', 't'));
-    if (!MessageQueue) return STATUS_INSUFFICIENT_RESOURCES;
-
-    /* Set it up */
-    KeInitializeSemaphore(&MessageQueue->Semaphore, 0, MAXLONG);
-    MessageQueue->BackPointer = Port;
-
-    /* And link it with the Paged Pool part */
-    Port->MsgQueue.Semaphore = &MessageQueue->Semaphore;
-    InitializeListHead(&Port->MsgQueue.ReceiveHead);
-    return STATUS_SUCCESS;
-}
-
-NTSTATUS
-NTAPI
-LpcpCreatePort(OUT PHANDLE PortHandle,
-               IN POBJECT_ATTRIBUTES ObjectAttributes,
-               IN ULONG MaxConnectionInfoLength,
-               IN ULONG MaxMessageLength,
-               IN ULONG MaxPoolUsage,
-               IN BOOLEAN Waitable)
-{
-    KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
-    NTSTATUS Status;
-    PLPCP_PORT_OBJECT Port;
-    LPCTRACE(LPC_CREATE_DEBUG, "Name: %wZ\n", ObjectAttributes->ObjectName);
-
-    /* Create the Object */
-    Status = ObCreateObject(PreviousMode,
-                            LpcPortObjectType,
-                            ObjectAttributes,
-                            PreviousMode,
-                            NULL,
-                            sizeof(LPCP_PORT_OBJECT),
-                            0,
-                            0,
-                            (PVOID*)&Port);
-    if (!NT_SUCCESS(Status)) return Status;
-
-    /* Set up the Object */
-    RtlZeroMemory(Port, sizeof(LPCP_PORT_OBJECT));
-    Port->ConnectionPort = Port;
-    Port->Creator = PsGetCurrentThread()->Cid;
-    InitializeListHead(&Port->LpcDataInfoChainHead);
-    InitializeListHead(&Port->LpcReplyChainHead);
-
-    /* Check if we don't have a name */
-    if (!ObjectAttributes->ObjectName->Buffer)
-    {
-        /* Set up for an unconnected port */
-        Port->Flags = LPCP_UNCONNECTED_PORT;
-        Port->ConnectedPort = Port;
-        Port->ServerProcess = NULL;
-    }
-    else
-    {
-        /* Set up for a named connection port */
-        Port->Flags = LPCP_CONNECTION_PORT;
-        Port->ServerProcess = PsGetCurrentProcess();
-
-        /* Don't let the process die on us */
-        ObReferenceObject(Port->ServerProcess);
-    }
-
-    /* Check if this is a waitable port */
-    if (Waitable) Port->Flags |= LPCP_WAITABLE_PORT;
-
-    /* Setup the port queue */
-    Status = LpcpInitializePortQueue(Port);
-    if (!NT_SUCCESS(Status))
-    {
-        /* Fail */
-        ObDereferenceObject(Port);
-        return Status;
-    }
-
-    /* Check if this is a waitable port */
-    if (Port->Flags & LPCP_WAITABLE_PORT)
-    {
-        /* Setup the wait event */
-        KeInitializeEvent(&Port->WaitEvent, NotificationEvent, FALSE);
-    }
-
-    /* Set the maximum message size allowed */
-    Port->MaxMessageLength = LpcpMaxMessageSize -
-                             FIELD_OFFSET(LPCP_MESSAGE, Request);
-
-    /* Now subtract the actual message structures and get the data size */
-    Port->MaxConnectionInfoLength = Port->MaxMessageLength -
-                                    sizeof(PORT_MESSAGE) -
-                                    sizeof(LPCP_CONNECTION_MESSAGE);
-
-    /* Validate the sizes */
-    if (Port->MaxConnectionInfoLength < MaxConnectionInfoLength)
-    {
-        /* Not enough space for your request */
-        ObDereferenceObject(Port);
-        return STATUS_INVALID_PARAMETER_3;
-    }
-    else if (Port->MaxMessageLength < MaxMessageLength)
-    {
-        /* Not enough space for your request */
-        ObDereferenceObject(Port);
-        return STATUS_INVALID_PARAMETER_4;
-    }
-
-    /* Now set the custom setting */
-    Port->MaxMessageLength = MaxMessageLength;
-
-    /* Insert it now */
-    Status = ObInsertObject((PVOID)Port,
-                            NULL,
-                            PORT_ALL_ACCESS,
-                            0,
-                            NULL,
-                            PortHandle);
-
-    /* Return success or the error */
-    LPCTRACE(LPC_CREATE_DEBUG, "Port: %p. Handle: %lx\n", Port, *PortHandle);
-    return Status;
-}
-
-/* PUBLIC FUNCTIONS **********************************************************/
-
-/*
- * @implemented
- */
-NTSTATUS
-NTAPI
-NtCreatePort(OUT PHANDLE PortHandle,
-             IN POBJECT_ATTRIBUTES ObjectAttributes,
-             IN ULONG MaxConnectInfoLength,
-             IN ULONG MaxDataLength,
-             IN ULONG MaxPoolUsage)
-{
-    PAGED_CODE();
-
-    /* Call the internal API */
-    return LpcpCreatePort(PortHandle,
-                          ObjectAttributes,
-                          MaxConnectInfoLength,
-                          MaxDataLength,
-                          MaxPoolUsage,
-                          FALSE);
-}
-
-/*
- * @implemented
- */
-NTSTATUS
-NTAPI
-NtCreateWaitablePort(OUT PHANDLE PortHandle,
-                     IN POBJECT_ATTRIBUTES ObjectAttributes,
-                     IN ULONG MaxConnectInfoLength,
-                     IN ULONG MaxDataLength,
-                     IN ULONG MaxPoolUsage)
-{
-    PAGED_CODE();
-
-    /* Call the internal API */
-    return LpcpCreatePort(PortHandle,
-                          ObjectAttributes,
-                          MaxConnectInfoLength,
-                          MaxDataLength,
-                          MaxPoolUsage,
-                          TRUE);
-}
-
-/* EOF */
diff --git a/reactos/ntoskrnl/lpc/ntlpc/listen.c b/reactos/ntoskrnl/lpc/ntlpc/listen.c
deleted file mode 100644 (file)
index ee2ade0..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * PROJECT:         ReactOS Kernel
- * LICENSE:         GPL - See COPYING in the top level directory
- * FILE:            ntoskrnl/lpc/listen.c
- * PURPOSE:         Local Procedure Call: Listening
- * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
- */
-
-/* INCLUDES ******************************************************************/
-
-#include <ntoskrnl.h>
-#include "lpc.h"
-#define NDEBUG
-#include <internal/debug.h>
-
-/* PUBLIC FUNCTIONS **********************************************************/
-
-/*
- * @implemented
- */
-NTSTATUS
-NTAPI
-NtListenPort(IN HANDLE PortHandle,
-             OUT PPORT_MESSAGE ConnectMessage)
-{
-        NTSTATUS Status;
-        PAGED_CODE();
-        LPCTRACE(LPC_LISTEN_DEBUG, "Handle: %lx\n", PortHandle);
-
-        /* Wait forever for a connection request. */
-        for (;;)
-        {
-            /* Do the wait */
-            Status = NtReplyWaitReceivePort(PortHandle,
-                                            NULL,
-                                            NULL,
-                                            ConnectMessage);
-
-            /* Accept only LPC_CONNECTION_REQUEST requests. */
-            if ((Status != STATUS_SUCCESS) ||
-                (LpcpGetMessageType(ConnectMessage) == LPC_CONNECTION_REQUEST))
-            {
-                /* Break out */
-                break;
-            }
-        }
-
-        /* Return status */
-        return Status;
-}
-
-
-/* EOF */
diff --git a/reactos/ntoskrnl/lpc/ntlpc/lpc.h b/reactos/ntoskrnl/lpc/ntlpc/lpc.h
deleted file mode 100644 (file)
index 5570e81..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
-* PROJECT:         ReactOS Kernel
-* LICENSE:         GPL - See COPYING in the top level directory
-* FILE:            ntoskrnl/include/lpc.h
-* PURPOSE:         Internal header for the Local Procedure Call
-* PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
-*/
-
-//
-// Define this if you want debugging support
-//
-#define _LPC_DEBUG_                                         0x01
-
-//
-// These define the Debug Masks Supported
-//
-#define LPC_CREATE_DEBUG                                    0x01
-#define LPC_CLOSE_DEBUG                                     0x02
-#define LPC_CONNECT_DEBUG                                   0x04
-#define LPC_LISTEN_DEBUG                                    0x08
-#define LPC_REPLY_DEBUG                                     0x10
-#define LPC_COMPLETE_DEBUG                                  0x20
-#define LPC_SEND_DEBUG                                      0x40
-
-//
-// Debug/Tracing support
-//
-#if _LPC_DEBUG_
-#ifdef NEW_DEBUG_SYSTEM_IMPLEMENTED // enable when Debug Filters are implemented
-#define LPCTRACE(x, ...)                                    \
-    {                                                       \
-        DbgPrintEx("%s [%.16s] - ",                         \
-                   __FUNCTION__,                            \
-                   PsGetCurrentProcess()->ImageFileName);   \
-        DbgPrintEx(__VA_ARGS__);                            \
-    }
-#else
-#define LPCTRACE(x, ...)                                    \
-    if (x & LpcpTraceLevel)                                 \
-    {                                                       \
-        DbgPrint("%s [%.16s:%lx] - ",                       \
-                 __FUNCTION__,                              \
-                 PsGetCurrentProcess()->ImageFileName,      \
-                 PsGetCurrentThreadId());                   \
-        DbgPrint(__VA_ARGS__);                              \
-    }
-#endif
-#endif
-
-//
-// Internal Port Management
-//
-VOID
-NTAPI
-LpcpClosePort(
-    IN PEPROCESS Process OPTIONAL,
-    IN PVOID Object,
-    IN ACCESS_MASK GrantedAccess,
-    IN ULONG ProcessHandleCount,
-    IN ULONG SystemHandleCount
-);
-
-VOID
-NTAPI
-LpcpDeletePort(
-    IN PVOID ObjectBody
-);
-
-NTSTATUS
-NTAPI
-LpcpInitializePortQueue(
-    IN PLPCP_PORT_OBJECT Port
-);
-
-VOID
-NTAPI
-LpcpFreeToPortZone(
-    IN PLPCP_MESSAGE Message,
-    IN ULONG Flags
-);
-
-VOID
-NTAPI
-LpcpMoveMessage(
-    IN PPORT_MESSAGE Destination,
-    IN PPORT_MESSAGE Origin,
-    IN PVOID Data,
-    IN ULONG MessageType,
-    IN PCLIENT_ID ClientId
-);
-
-VOID
-NTAPI
-LpcpSaveDataInfoMessage(
-    IN PLPCP_PORT_OBJECT Port,
-    IN PLPCP_MESSAGE Message
-);
-
-//
-// Module-external utlity functions
-//
-VOID
-NTAPI
-LpcExitThread(
-    IN PETHREAD Thread
-);
-
-//
-// Initialization functions
-//
-NTSTATUS
-NTAPI
-LpcpInitSystem(
-    VOID
-);
-
-//
-// Global data inside the Process Manager
-//
-extern POBJECT_TYPE LpcPortObjectType;
-extern ULONG LpcpNextMessageId, LpcpNextCallbackId;
-extern KGUARDED_MUTEX LpcpLock;
-extern PAGED_LOOKASIDE_LIST LpcpMessagesLookaside;
-extern ULONG LpcpMaxMessageSize;
-extern ULONG LpcpTraceLevel;
-
-//
-// Inlined Functions
-//
-#include "lpc_x.h"
diff --git a/reactos/ntoskrnl/lpc/ntlpc/port.c b/reactos/ntoskrnl/lpc/ntlpc/port.c
deleted file mode 100644 (file)
index dcc5a97..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * PROJECT:         ReactOS Kernel
- * LICENSE:         GPL - See COPYING in the top level directory
- * FILE:            ntoskrnl/lpc/port.c
- * PURPOSE:         Local Procedure Call: Port Management
- * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
- */
-
-/* INCLUDES ******************************************************************/
-
-#include <ntoskrnl.h>
-#include "lpc.h"
-#define NDEBUG
-#include <internal/debug.h>
-
-/* GLOBALS *******************************************************************/
-
-POBJECT_TYPE LpcPortObjectType;
-ULONG LpcpMaxMessageSize;
-PAGED_LOOKASIDE_LIST LpcpMessagesLookaside;
-KGUARDED_MUTEX LpcpLock;
-ULONG LpcpTraceLevel = LPC_CLOSE_DEBUG;
-ULONG LpcpNextMessageId = 1, LpcpNextCallbackId = 1;
-
-static GENERIC_MAPPING LpcpPortMapping = 
-{
-    STANDARD_RIGHTS_READ,
-    STANDARD_RIGHTS_WRITE,
-    0,
-    PORT_ALL_ACCESS
-};
-
-/* PRIVATE FUNCTIONS *********************************************************/
-
-NTSTATUS
-INIT_FUNCTION
-NTAPI
-LpcpInitSystem(VOID)
-{
-    OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
-    UNICODE_STRING Name;
-
-    /* Setup the LPC Lock */
-    KeInitializeGuardedMutex(&LpcpLock);
-
-    /* Create the Port Object Type */
-    RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
-    RtlInitUnicodeString(&Name, L"Port");
-    ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
-    ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(LPCP_PORT_OBJECT);
-    ObjectTypeInitializer.DefaultPagedPoolCharge = sizeof(LPCP_NONPAGED_PORT_QUEUE);
-    ObjectTypeInitializer.GenericMapping = LpcpPortMapping;
-    ObjectTypeInitializer.PoolType = PagedPool;
-    ObjectTypeInitializer.UseDefaultObject = TRUE;
-    ObjectTypeInitializer.CloseProcedure = LpcpClosePort;
-    ObjectTypeInitializer.DeleteProcedure = LpcpDeletePort;
-    ObjectTypeInitializer.ValidAccessMask = PORT_ALL_ACCESS;
-    ObjectTypeInitializer.MaintainTypeList = TRUE;
-    ObCreateObjectType(&Name,
-                       &ObjectTypeInitializer,
-                       NULL,
-                       &LpcPortObjectType);
-
-    /* Allocate the LPC lookaside list */
-    LpcpMaxMessageSize = LPCP_MAX_MESSAGE_SIZE;
-    ExInitializePagedLookasideList(&LpcpMessagesLookaside,
-                                   NULL,
-                                   NULL,
-                                   0,
-                                   LpcpMaxMessageSize,
-                                   TAG('L', 'p', 'c', 'M'),
-                                   32);
-
-    /* We're done */
-    return STATUS_SUCCESS;
-}
-
-/* PUBLIC FUNCTIONS **********************************************************/
-
-NTSTATUS
-NTAPI
-NtImpersonateClientOfPort(IN HANDLE PortHandle,
-                          IN PPORT_MESSAGE ClientMessage)
-{
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
-}
-
-NTSTATUS
-NTAPI
-NtQueryPortInformationProcess(VOID)
-{
-    /* This is all this function does */
-    return STATUS_UNSUCCESSFUL;
-}
-
-NTSTATUS
-NTAPI
-NtQueryInformationPort(IN HANDLE PortHandle,
-                       IN PORT_INFORMATION_CLASS PortInformationClass,
-                       OUT PVOID PortInformation,
-                       IN ULONG PortInformationLength,
-                       OUT PULONG ReturnLength)
-{
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
-}
-
-/* EOF */
diff --git a/reactos/ntoskrnl/lpc/ntlpc/reply.c b/reactos/ntoskrnl/lpc/ntlpc/reply.c
deleted file mode 100644 (file)
index 311002e..0000000
+++ /dev/null
@@ -1,491 +0,0 @@
-/*
- * PROJECT:         ReactOS Kernel
- * LICENSE:         GPL - See COPYING in the top level directory
- * FILE:            ntoskrnl/lpc/reply.c
- * PURPOSE:         Local Procedure Call: Receive (Replies)
- * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
- */
-
-/* INCLUDES ******************************************************************/
-
-#include <ntoskrnl.h>
-#include "lpc.h"
-#define NDEBUG
-#include <internal/debug.h>
-
-/* PRIVATE FUNCTIONS *********************************************************/
-
-VOID
-NTAPI
-LpcpFreeDataInfoMessage(IN PLPCP_PORT_OBJECT Port,
-                        IN ULONG MessageId,
-                        IN ULONG CallbackId)
-{
-    PLPCP_MESSAGE Message;
-    PLIST_ENTRY ListHead, NextEntry;
-
-    /* Check if the port we want is the connection port */
-    if ((Port->Flags & LPCP_PORT_TYPE_MASK) > LPCP_UNCONNECTED_PORT)
-    {
-        /* Use it */
-        Port = Port->ConnectionPort;
-    }
-
-    /* Loop the list */
-    ListHead = &Port->LpcDataInfoChainHead;
-    NextEntry = ListHead->Flink;
-    while (ListHead != NextEntry)
-    {
-        /* Get the message */
-        Message = CONTAINING_RECORD(NextEntry, LPCP_MESSAGE, Entry);
-
-        /* Make sure it matches */
-        if ((Message->Request.MessageId == MessageId) &&
-            (Message->Request.CallbackId == CallbackId))
-        {
-            /* Unlink and free it */
-            RemoveEntryList(&Message->Entry);
-            InitializeListHead(&Message->Entry);
-            LpcpFreeToPortZone(Message, TRUE);
-            break;
-        }
-
-        /* Go to the next entry */
-        NextEntry = NextEntry->Flink;
-    }
-}
-
-VOID
-NTAPI
-LpcpSaveDataInfoMessage(IN PLPCP_PORT_OBJECT Port,
-                        IN PLPCP_MESSAGE Message)
-{
-    PAGED_CODE();
-
-    /* Acquire the lock */
-    KeAcquireGuardedMutex(&LpcpLock);
-
-    /* Check if the port we want is the connection port */
-    if ((Port->Flags & LPCP_PORT_TYPE_MASK) > LPCP_UNCONNECTED_PORT)
-    {
-        /* Use it */
-        Port = Port->ConnectionPort;
-    }
-
-    /* Link the message */
-    InsertTailList(&Port->LpcDataInfoChainHead, &Message->Entry);
-
-    /* Release the lock */
-    KeReleaseGuardedMutex(&LpcpLock);
-}
-
-VOID
-NTAPI
-LpcpMoveMessage(IN PPORT_MESSAGE Destination,
-                IN PPORT_MESSAGE Origin,
-                IN PVOID Data,
-                IN ULONG MessageType,
-                IN PCLIENT_ID ClientId)
-{
-    /* Set the Message size */
-    LPCTRACE((LPC_REPLY_DEBUG | LPC_SEND_DEBUG),
-             "Destination/Origin: %p/%p. Data: %p. Length: %lx\n",
-             Destination,
-             Origin,
-             Data,
-             Origin->u1.Length);
-    Destination->u1.Length = Origin->u1.Length;
-
-    /* Set the Message Type */
-    Destination->u2.s2.Type = !MessageType ?
-                              Origin->u2.s2.Type : MessageType & 0xFFFF;
-
-    /* Check if we have a Client ID */
-    if (ClientId)
-    {
-        /* Set the Client ID */
-        Destination->ClientId.UniqueProcess = ClientId->UniqueProcess;
-        Destination->ClientId.UniqueThread = ClientId->UniqueThread;
-    }
-    else
-    {
-        /* Otherwise, copy it */
-        Destination->ClientId.UniqueProcess = Origin->ClientId.UniqueProcess;
-        Destination->ClientId.UniqueThread = Origin->ClientId.UniqueThread;
-    }
-
-    /* Copy the MessageId and ClientViewSize */
-    Destination->MessageId = Origin->MessageId;
-    Destination->ClientViewSize = Origin->ClientViewSize;
-
-    /* Copy the Message Data */
-    RtlMoveMemory(Destination + 1,
-                  Data,
-                  ((Destination->u1.Length & 0xFFFF) + 3) &~3);
-}
-
-/* PUBLIC FUNCTIONS **********************************************************/
-
-/*
- * @unimplemented
- */
-NTSTATUS
-NTAPI
-NtReplyPort(IN HANDLE PortHandle,
-            IN PPORT_MESSAGE LpcReply)
-{
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
-}
-
-/*
- * @implemented
- */
-NTSTATUS
-NTAPI
-NtReplyWaitReceivePortEx(IN HANDLE PortHandle,
-                         OUT PVOID *PortContext OPTIONAL,
-                         IN PPORT_MESSAGE ReplyMessage OPTIONAL,
-                         OUT PPORT_MESSAGE ReceiveMessage,
-                         IN PLARGE_INTEGER Timeout OPTIONAL)
-{
-    PLPCP_PORT_OBJECT Port, ReceivePort;
-    KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(), WaitMode = PreviousMode;
-    NTSTATUS Status;
-    PLPCP_MESSAGE Message;
-    PETHREAD Thread = PsGetCurrentThread(), WakeupThread;
-    PLPCP_CONNECTION_MESSAGE ConnectMessage;
-    ULONG ConnectionInfoLength;
-    PAGED_CODE();
-    LPCTRACE(LPC_REPLY_DEBUG,
-             "Handle: %lx. Messages: %p/%p. Context: %p\n",
-             PortHandle,
-             ReplyMessage,
-             ReceiveMessage,
-             PortContext);
-
-    /* If this is a system thread, then let it page out its stack */
-    if (Thread->SystemThread) WaitMode = UserMode;
-
-    /* Check if caller has a reply message */
-    if (ReplyMessage)
-    {
-        /* Validate its length */
-        if ((ReplyMessage->u1.s1.DataLength + sizeof(PORT_MESSAGE)) >
-            ReplyMessage->u1.s1.TotalLength)
-        {
-            /* Fail */
-            return STATUS_INVALID_PARAMETER;
-        }
-
-        /* Make sure it has a valid ID */
-        if (!ReplyMessage->MessageId) return STATUS_INVALID_PARAMETER;
-    }
-
-    /* Get the Port object */
-    Status = ObReferenceObjectByHandle(PortHandle,
-                                       0,
-                                       LpcPortObjectType,
-                                       PreviousMode,
-                                       (PVOID*)&Port,
-                                       NULL);
-    if (!NT_SUCCESS(Status)) return Status;
-
-    /* Check if the caller has a reply message */
-    if (ReplyMessage)
-    {
-        /* Validate its length in respect to the port object */
-        if ((ReplyMessage->u1.s1.TotalLength > Port->MaxMessageLength) ||
-            (ReplyMessage->u1.s1.TotalLength <= ReplyMessage->u1.s1.DataLength))
-        {
-            /* Too large, fail */
-            ObDereferenceObject(Port);
-            return STATUS_PORT_MESSAGE_TOO_LONG;
-        }
-    }
-
-    /* Check if this is anything but a client port */
-    if ((Port->Flags & LPCP_PORT_TYPE_MASK) != LPCP_CLIENT_PORT)
-    {
-        /* Use the connection port */
-        ReceivePort = Port->ConnectionPort;
-    }
-    else
-    {
-        /* Otherwise, use the port itself */
-        ReceivePort = Port;
-    }
-
-    /* Check if the caller gave a reply message */
-    if (ReplyMessage)
-    {
-        /* Get the ETHREAD corresponding to it */
-        Status = PsLookupProcessThreadByCid(&ReplyMessage->ClientId,
-                                            NULL,
-                                            &WakeupThread);
-        if (!NT_SUCCESS(Status))
-        {
-            /* No thread found, fail */
-            ObDereferenceObject(Port);
-            return Status;
-        }
-
-        /* Allocate a message from the port zone */
-        Message = LpcpAllocateFromPortZone();
-        if (!Message)
-        {
-            /* Fail if we couldn't allocate a message */
-            ObDereferenceObject(WakeupThread);
-            ObDereferenceObject(Port);
-            return STATUS_NO_MEMORY;
-        }
-
-        /* Keep the lock acquired */
-        KeAcquireGuardedMutex(&LpcpLock);
-
-        /* Make sure this is the reply the thread is waiting for */
-        if (WakeupThread->LpcReplyMessageId != ReplyMessage->MessageId)
-        {
-            /* It isn't, fail */
-            LpcpFreeToPortZone(Message, TRUE);
-            KeReleaseGuardedMutex(&LpcpLock);
-            ObDereferenceObject(WakeupThread);
-            ObDereferenceObject(Port);
-            return STATUS_REPLY_MESSAGE_MISMATCH;
-        }
-
-        /* Copy the message */
-        LpcpMoveMessage(&Message->Request,
-                        ReplyMessage,
-                        ReplyMessage + 1,
-                        LPC_REPLY,
-                        NULL);
-
-        /* Free any data information */
-        LpcpFreeDataInfoMessage(Port,
-                                ReplyMessage->MessageId,
-                                ReplyMessage->CallbackId);
-
-        /* Reference the thread while we use it */
-        ObReferenceObject(WakeupThread);
-        Message->RepliedToThread = WakeupThread;
-
-        /* Set this as the reply message */
-        WakeupThread->LpcReplyMessageId = 0;
-        WakeupThread->LpcReplyMessage = (PVOID)Message;
-
-        /* Check if we have messages on the reply chain */
-        if (!(WakeupThread->LpcExitThreadCalled) &&
-            !(IsListEmpty(&WakeupThread->LpcReplyChain)))
-        {
-            /* Remove us from it and reinitialize it */
-            RemoveEntryList(&WakeupThread->LpcReplyChain);
-            InitializeListHead(&WakeupThread->LpcReplyChain);
-        }
-
-        /* Check if this is the message the thread had received */
-        if ((Thread->LpcReceivedMsgIdValid) &&
-            (Thread->LpcReceivedMessageId == ReplyMessage->MessageId))
-        {
-            /* Clear this data */
-            Thread->LpcReceivedMessageId = 0;
-            Thread->LpcReceivedMsgIdValid = FALSE;
-        }
-
-        /* Release the lock and release the LPC semaphore to wake up waiters */
-        KeReleaseGuardedMutex(&LpcpLock);
-        LpcpCompleteWait(&WakeupThread->LpcReplySemaphore);
-
-        /* Now we can let go of the thread */
-        ObDereferenceObject(WakeupThread);
-    }
-
-    /* Now wait for someone to reply to us */
-    LpcpReceiveWait(ReceivePort->MsgQueue.Semaphore, WaitMode);
-    if (Status != STATUS_SUCCESS) goto Cleanup;
-
-    /* Wait done, get the LPC lock */
-    KeAcquireGuardedMutex(&LpcpLock);
-
-    /* Check if we've received nothing */
-    if (IsListEmpty(&ReceivePort->MsgQueue.ReceiveHead))
-    {
-        /* Check if this was a waitable port and wake it */
-        if (ReceivePort->Flags & LPCP_WAITABLE_PORT)
-        {
-            /* Reset its event */
-            KeResetEvent(&ReceivePort->WaitEvent);
-        }
-
-        /* Release the lock and fail */
-        KeReleaseGuardedMutex(&LpcpLock);
-        ObDereferenceObject(Port);
-        return STATUS_UNSUCCESSFUL;
-    }
-
-    /* Get the message on the queue */
-    Message = CONTAINING_RECORD(RemoveHeadList(&ReceivePort->
-                                               MsgQueue.ReceiveHead),
-                                LPCP_MESSAGE,
-                                Entry);
-
-    /* Check if the queue is empty now */
-    if (IsListEmpty(&ReceivePort->MsgQueue.ReceiveHead))
-    {
-        /* Check if this was a waitable port */
-        if (ReceivePort->Flags & LPCP_WAITABLE_PORT)
-        {
-            /* Reset its event */
-            KeResetEvent(&ReceivePort->WaitEvent);
-        }
-    }
-
-    /* Re-initialize the message's list entry */
-    InitializeListHead(&Message->Entry);
-
-    /* Set this as the received message */
-    Thread->LpcReceivedMessageId = Message->Request.MessageId;
-    Thread->LpcReceivedMsgIdValid = TRUE;
-
-    /* Done touching global data, release the lock */
-    KeReleaseGuardedMutex(&LpcpLock);
-
-    /* Check if this was a connection request */
-    if (LpcpGetMessageType(&Message->Request) == LPC_CONNECTION_REQUEST)
-    {
-        /* Get the connection message */
-        ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(Message + 1);
-        LPCTRACE(LPC_REPLY_DEBUG,
-                 "Request Messages: %p/%p\n",
-                 Message,
-                 ConnectMessage);
-
-        /* Get its length */
-        ConnectionInfoLength = Message->Request.u1.s1.DataLength -
-                               sizeof(LPCP_CONNECTION_MESSAGE);
-
-        /* Return it as the receive message */
-        *ReceiveMessage = Message->Request;
-
-        /* Clear our stack variable so the message doesn't get freed */
-        Message = NULL;
-
-        /* Setup the receive message */
-        ReceiveMessage->u1.s1.TotalLength = sizeof(LPCP_MESSAGE) +
-                                            ConnectionInfoLength;
-        ReceiveMessage->u1.s1.DataLength = ConnectionInfoLength;
-        RtlMoveMemory(ReceiveMessage + 1,
-                      ConnectMessage + 1,
-                      ConnectionInfoLength);
-
-        /* Clear the port context if the caller requested one */
-        if (PortContext) *PortContext = NULL;
-    }
-    else if (Message->Request.u2.s2.Type != LPC_REPLY)
-    {
-        /* Otherwise, this is a new message or event */
-        LPCTRACE(LPC_REPLY_DEBUG,
-                 "Non-Reply Messages: %p/%p\n",
-                 &Message->Request,
-                 (&Message->Request) + 1);
-
-        /* Copy it */
-        LpcpMoveMessage(ReceiveMessage,
-                        &Message->Request,
-                        (&Message->Request) + 1,
-                        0,
-                        NULL);
-
-        /* Return its context */
-        if (PortContext) *PortContext = Message->PortContext;
-
-        /* And check if it has data information */
-        if (Message->Request.u2.s2.DataInfoOffset)
-        {
-            /* It does, save it, and don't free the message below */
-            LpcpSaveDataInfoMessage(Port, Message);
-            Message = NULL;
-        }
-    }
-    else
-    {
-        /* This is a reply message, should never happen! */
-        ASSERT(FALSE);
-    }
-
-    /* If we have a message pointer here, free it */
-    if (Message) LpcpFreeToPortZone(Message, FALSE);
-
-Cleanup:
-    /* All done, dereference the port and return the status */
-    LPCTRACE(LPC_REPLY_DEBUG,
-             "Port: %p. Status: %p\n",
-             Port,
-             Status);
-    ObDereferenceObject(Port);
-    return Status;
-}
-
-/*
- * @implemented
- */
-NTSTATUS
-NTAPI
-NtReplyWaitReceivePort(IN HANDLE PortHandle,
-                       OUT PVOID *PortContext OPTIONAL,
-                       IN PPORT_MESSAGE ReplyMessage OPTIONAL,
-                       OUT PPORT_MESSAGE ReceiveMessage)
-{
-    /* Call the newer API */
-    return NtReplyWaitReceivePortEx(PortHandle,
-                                    PortContext,
-                                    ReplyMessage,
-                                    ReceiveMessage,
-                                    NULL);
-}
-
-/*
- * @unimplemented
- */
-NTSTATUS
-NTAPI
-NtReplyWaitReplyPort(IN HANDLE PortHandle,
-                     IN PPORT_MESSAGE ReplyMessage)
-{
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
-}
-
-/*
- * @unimplemented
- */
-NTSTATUS
-NTAPI
-NtReadRequestData(IN HANDLE PortHandle,
-                  IN PPORT_MESSAGE Message,
-                  IN ULONG Index,
-                  IN PVOID Buffer,
-                  IN ULONG BufferLength,
-                  OUT PULONG Returnlength)
-{
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
-}
-
-/*
- * @unimplemented
- */
-NTSTATUS
-NTAPI
-NtWriteRequestData(IN HANDLE PortHandle,
-                   IN PPORT_MESSAGE Message,
-                   IN ULONG Index,
-                   IN PVOID Buffer,
-                   IN ULONG BufferLength,
-                   OUT PULONG ReturnLength)
-{
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
-}
-
-/* EOF */
diff --git a/reactos/ntoskrnl/lpc/ntlpc/send.c b/reactos/ntoskrnl/lpc/ntlpc/send.c
deleted file mode 100644 (file)
index f49e0a6..0000000
+++ /dev/null
@@ -1,426 +0,0 @@
-/*
- * PROJECT:         ReactOS Kernel
- * LICENSE:         GPL - See COPYING in the top level directory
- * FILE:            ntoskrnl/lpc/send.c
- * PURPOSE:         Local Procedure Call: Sending (Requests)
- * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
- */
-
-/* INCLUDES ******************************************************************/
-
-#include <ntoskrnl.h>
-#include "lpc.h"
-#define NDEBUG
-#include <internal/debug.h>
-
-/* PUBLIC FUNCTIONS **********************************************************/
-
-/*
- * @implemented
- */
-NTSTATUS
-NTAPI
-LpcRequestPort(IN PVOID PortObject,
-               IN PPORT_MESSAGE LpcMessage)
-{
-    PLPCP_PORT_OBJECT Port = (PLPCP_PORT_OBJECT)PortObject, QueuePort;
-    ULONG MessageType;
-    PLPCP_MESSAGE Message;
-    KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
-    PAGED_CODE();
-    LPCTRACE(LPC_SEND_DEBUG, "Port: %p. Message: %p\n", Port, LpcMessage);
-
-    /* Check if this is a non-datagram message */
-    if (LpcMessage->u2.s2.Type)
-    {
-        /* Get the message type */
-        MessageType = LpcpGetMessageType(LpcMessage);
-
-        /* Validate it */
-        if ((MessageType < LPC_DATAGRAM) || (MessageType > LPC_CLIENT_DIED))
-        {
-            /* Fail */
-            return STATUS_INVALID_PARAMETER;
-        }
-
-        /* Mark this as a kernel-mode message only if we really came from there */
-        if ((PreviousMode == KernelMode) &&
-            (LpcMessage->u2.s2.Type & LPC_KERNELMODE_MESSAGE))
-        {
-            /* We did, this is a kernel mode message */
-            MessageType |= LPC_KERNELMODE_MESSAGE;
-        }
-    }
-    else
-    {
-        /* This is a datagram */
-        MessageType = LPC_DATAGRAM;
-    }
-
-    /* Can't have data information on this type of call */
-    if (LpcMessage->u2.s2.DataInfoOffset) return STATUS_INVALID_PARAMETER;
-
-    /* Validate message sizes */
-    if ((LpcMessage->u1.s1.TotalLength > Port->MaxMessageLength) ||
-        (LpcMessage->u1.s1.TotalLength <= LpcMessage->u1.s1.DataLength))
-    {
-        /* Fail */
-        return STATUS_PORT_MESSAGE_TOO_LONG;
-    }
-
-    /* Allocate a new message */
-    Message = LpcpAllocateFromPortZone();
-    if (!Message) return STATUS_NO_MEMORY;
-
-    /* Clear the context */
-    Message->PortContext = NULL;
-
-    /* Copy the message */
-    LpcpMoveMessage(&Message->Request,
-                    LpcMessage,
-                    LpcMessage + 1,
-                    MessageType,
-                    &PsGetCurrentThread()->Cid);
-
-    /* Acquire the LPC lock */
-    KeAcquireGuardedMutex(&LpcpLock);
-
-    /* Check if this is anything but a connection port */
-    if ((Port->Flags & LPCP_PORT_TYPE_MASK) != LPCP_CONNECTION_PORT)
-    {
-        /* The queue port is the connected port */
-        QueuePort = Port->ConnectedPort;
-        if (QueuePort)
-        {
-            /* Check if this is a client port */
-            if ((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_CLIENT_PORT)
-            {
-                /* Then copy the context */
-                Message->PortContext = QueuePort->PortContext;
-                QueuePort = Port->ConnectionPort;
-            }
-            else if ((Port->Flags & LPCP_PORT_TYPE_MASK) != LPCP_COMMUNICATION_PORT)
-            {
-                /* Any other kind of port, use the connection port */
-                QueuePort = Port->ConnectionPort;
-            }
-        }
-    }
-    else
-    {
-        /* For connection ports, use the port itself */
-        QueuePort = PortObject;
-    }
-
-    /* Make sure we have a port */
-    if (QueuePort)
-    {
-        /* Generate the Message ID and set it */
-        Message->Request.MessageId =  LpcpNextMessageId++;
-        if (!LpcpNextMessageId) LpcpNextMessageId = 1;
-        Message->Request.CallbackId = 0;
-
-        /* No Message ID for the thread */
-        PsGetCurrentThread()->LpcReplyMessageId = 0;
-
-        /* Insert the message in our chain */
-        InsertTailList(&QueuePort->MsgQueue.ReceiveHead, &Message->Entry);
-
-        /* Release the lock and release the semaphore */
-        KeReleaseGuardedMutex(&LpcpLock);
-        LpcpCompleteWait(QueuePort->MsgQueue.Semaphore);
-
-        /* If this is a waitable port, wake it up */
-        if (QueuePort->Flags & LPCP_WAITABLE_PORT)
-        {
-            /* Wake it */
-            KeSetEvent(&QueuePort->WaitEvent, IO_NO_INCREMENT, FALSE);
-        }
-
-        /* We're done */
-        LPCTRACE(LPC_SEND_DEBUG, "Port: %p. Message: %p\n", QueuePort, Message);
-        return STATUS_SUCCESS;
-    }
-
-    /* If we got here, then free the message and fail */
-    LpcpFreeToPortZone(Message, TRUE);
-    KeReleaseGuardedMutex(&LpcpLock);
-    return STATUS_PORT_DISCONNECTED;
-}
-
-/*
-* @unimplemented
-*/
-NTSTATUS
-NTAPI
-LpcRequestWaitReplyPort(IN PVOID Port,
-                        IN PPORT_MESSAGE LpcMessageRequest,
-                        OUT PPORT_MESSAGE LpcMessageReply)
-{
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
-}
-
-/*
- * @unimplemented
- */
-NTSTATUS
-NTAPI
-NtRequestPort(IN HANDLE PortHandle,
-              IN PPORT_MESSAGE LpcMessage)
-{
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
-}
-
-/*
- * @implemented
- */
-NTSTATUS
-NTAPI
-NtRequestWaitReplyPort(IN HANDLE PortHandle,
-                       IN PPORT_MESSAGE LpcRequest,
-                       IN OUT PPORT_MESSAGE LpcReply)
-{
-    PLPCP_PORT_OBJECT Port, QueuePort, ReplyPort;
-    KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
-    NTSTATUS Status;
-    PLPCP_MESSAGE Message;
-    PETHREAD Thread = PsGetCurrentThread();
-    BOOLEAN Callback;
-    PKSEMAPHORE Semaphore;
-    ULONG MessageType;
-    PAGED_CODE();
-    LPCTRACE(LPC_SEND_DEBUG,
-             "Handle: %lx. Messages: %p/%p. Type: %lx\n",
-             PortHandle,
-             LpcRequest,
-             LpcReply,
-             LpcpGetMessageType(LpcRequest));
-
-    /* Check if the thread is dying */
-    if (Thread->LpcExitThreadCalled) return STATUS_THREAD_IS_TERMINATING;
-
-    /* Check if this is an LPC Request */
-    if (LpcpGetMessageType(LpcRequest) == LPC_REQUEST)
-    {
-        /* Then it's a callback */
-        Callback = TRUE;
-    }
-    else if (LpcpGetMessageType(LpcRequest))
-    {
-        /* This is a not kernel-mode message */
-        return STATUS_INVALID_PARAMETER;
-    }
-    else
-    {
-        /* This is a kernel-mode message without a callback */
-        LpcRequest->u2.s2.Type |= LPC_REQUEST;
-        Callback = FALSE;
-    }
-
-    /* Get the message type */
-    MessageType = LpcRequest->u2.s2.Type;
-
-    /* Validate the length */
-    if ((LpcRequest->u1.s1.DataLength + sizeof(PORT_MESSAGE)) >
-         LpcRequest->u1.s1.TotalLength)
-    {
-        /* Fail */
-        return STATUS_INVALID_PARAMETER;
-    }
-
-    /* Reference the object */
-    Status = ObReferenceObjectByHandle(PortHandle,
-                                       0,
-                                       LpcPortObjectType,
-                                       PreviousMode,
-                                       (PVOID*)&Port,
-                                       NULL);
-    if (!NT_SUCCESS(Status)) return Status;
-
-    /* Validate the message length */
-    if ((LpcRequest->u1.s1.TotalLength > Port->MaxMessageLength) ||
-        (LpcRequest->u1.s1.TotalLength <= LpcRequest->u1.s1.DataLength))
-    {
-        /* Fail */
-        ObDereferenceObject(Port);
-        return STATUS_PORT_MESSAGE_TOO_LONG;
-    }
-
-    /* Allocate a message from the port zone */
-    Message = LpcpAllocateFromPortZone();
-    if (!Message)
-    {
-        /* Fail if we couldn't allocate a message */
-        ObDereferenceObject(Port);
-        return STATUS_NO_MEMORY;
-    }
-
-    /* Check if this is a callback */
-    if (Callback)
-    {
-        /* FIXME: TODO */
-        Semaphore = NULL; // we'd use the Thread Semaphore here
-        ASSERT(FALSE);
-    }
-    else
-    {
-        /* No callback, just copy the message */
-        LpcpMoveMessage(&Message->Request,
-                        LpcRequest,
-                        LpcRequest + 1,
-                        MessageType,
-                        &Thread->Cid);
-
-        /* Acquire the LPC lock */
-        KeAcquireGuardedMutex(&LpcpLock);
-
-        /* Right now clear the port context */
-        Message->PortContext = NULL;
-
-        /* Check if this is a not connection port */
-        if ((Port->Flags & LPCP_PORT_TYPE_MASK) != LPCP_CONNECTION_PORT)
-        {
-            /* We want the connected port */
-            QueuePort = Port->ConnectedPort;
-            if (!QueuePort)
-            {
-                /* We have no connected port, fail */
-                LpcpFreeToPortZone(Message, TRUE);
-                KeReleaseGuardedMutex(&LpcpLock);
-                ObDereferenceObject(Port);
-                return STATUS_PORT_DISCONNECTED;
-            }
-
-            /* This will be the rundown port */
-            ReplyPort = QueuePort;
-
-            /* Check if this is a communication port */
-            if ((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_CLIENT_PORT)
-            {
-                /* Copy the port context and use the connection port */
-                Message->PortContext = ReplyPort->PortContext;
-                QueuePort = Port->ConnectionPort;
-            }
-            else if ((Port->Flags & LPCP_PORT_TYPE_MASK) !=
-                      LPCP_COMMUNICATION_PORT)
-            {
-                /* Use the connection port for anything but communication ports */
-                QueuePort = Port->ConnectionPort;
-            }
-        }
-        else
-        {
-            /* Otherwise, for a connection port, use the same port object */
-            QueuePort = ReplyPort = Port;
-        }
-
-        /* No reply thread */
-        Message->RepliedToThread = NULL;
-
-        /* Generate the Message ID and set it */
-        Message->Request.MessageId =  LpcpNextMessageId++;
-        if (!LpcpNextMessageId) LpcpNextMessageId = 1;
-        Message->Request.CallbackId = 0;
-
-        /* Set the message ID for our thread now */
-        Thread->LpcReplyMessageId = Message->Request.MessageId;
-        Thread->LpcReplyMessage = NULL;
-
-        /* Insert the message in our chain */
-        InsertTailList(&QueuePort->MsgQueue.ReceiveHead, &Message->Entry);
-        InsertTailList(&ReplyPort->LpcReplyChainHead, &Thread->LpcReplyChain);
-
-        /* Release the lock and get the semaphore we'll use later */
-        KeReleaseGuardedMutex(&LpcpLock);
-        Semaphore = QueuePort->MsgQueue.Semaphore;
-
-        /* If this is a waitable port, wake it up */
-        if (QueuePort->Flags & LPCP_WAITABLE_PORT)
-        {
-            /* Wake it */
-            KeSetEvent(&QueuePort->WaitEvent, IO_NO_INCREMENT, FALSE);
-        }
-    }
-
-    /* Now release the semaphore */
-    LpcpCompleteWait(Semaphore);
-
-    /* And let's wait for the reply */
-    LpcpReplyWait(&Thread->LpcReplySemaphore, PreviousMode);
-
-    /* Acquire the LPC lock */
-    KeAcquireGuardedMutex(&LpcpLock);
-
-    /* Get the LPC Message and clear our thread's reply data */
-    Message = Thread->LpcReplyMessage;
-    Thread->LpcReplyMessage = NULL;
-    Thread->LpcReplyMessageId = 0;
-
-    /* Check if we have anything on the reply chain*/
-    if (!IsListEmpty(&Thread->LpcReplyChain))
-    {
-        /* Remove this thread and reinitialize the list */
-        RemoveEntryList(&Thread->LpcReplyChain);
-        InitializeListHead(&Thread->LpcReplyChain);
-    }
-
-    /* Release the lock */
-    KeReleaseGuardedMutex(&LpcpLock);
-
-    /* Check if we got a reply */
-    if (Status == STATUS_SUCCESS)
-    {
-        /* Check if we have a valid message */
-        if (Message)
-        {
-            LPCTRACE(LPC_SEND_DEBUG,
-                     "Reply Messages: %p/%p\n",
-                     &Message->Request,
-                     (&Message->Request) + 1);
-
-            /* Move the message */
-            LpcpMoveMessage(LpcReply,
-                            &Message->Request,
-                            (&Message->Request) + 1,
-                            0,
-                            NULL);
-
-            /* Check if this is an LPC request with data information */
-            if ((LpcpGetMessageType(&Message->Request) == LPC_REQUEST) &&
-                (Message->Request.u2.s2.DataInfoOffset))
-            {
-                /* Save the data information */
-                LpcpSaveDataInfoMessage(Port, Message);
-            }
-            else
-            {
-                /* Otherwise, just free it */
-                LpcpFreeToPortZone(Message, FALSE);
-            }
-        }
-        else
-        {
-            /* We don't have a reply */
-            Status = STATUS_LPC_REPLY_LOST;
-        }
-    }
-    else
-    {
-        /* The wait failed, free the message while holding the lock */
-        KeAcquireGuardedMutex(&LpcpLock);
-        LpcpFreeToPortZone(Message, TRUE);
-        KeReleaseGuardedMutex(&LpcpLock);
-    }
-
-    /* All done */
-    LPCTRACE(LPC_SEND_DEBUG,
-             "Port: %p. Status: %p\n",
-             Port,
-             Status);
-    ObDereferenceObject(Port);
-    return Status;
-}
-
-/* EOF */
index 18fec96..dcc5a97 100644 (file)
@@ -1,29 +1,26 @@
-/* $Id$
- *
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS kernel
+/*
+ * PROJECT:         ReactOS Kernel
+ * LICENSE:         GPL - See COPYING in the top level directory
  * FILE:            ntoskrnl/lpc/port.c
- * PURPOSE:         Communication mechanism
- *
- * PROGRAMMERS:     David Welch (welch@cwcom.net)
+ * PURPOSE:         Local Procedure Call: Port Management
+ * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
  */
 
-/* INCLUDES *****************************************************************/
+/* INCLUDES ******************************************************************/
 
 #include <ntoskrnl.h>
+#include "lpc.h"
 #define NDEBUG
 #include <internal/debug.h>
 
-#if defined (ALLOC_PRAGMA)
-#pragma alloc_text(INIT, LpcpInitSystem)
-#endif
-
 /* GLOBALS *******************************************************************/
 
-POBJECT_TYPE   LpcPortObjectType = 0;
-ULONG          LpcpNextMessageId = 0; /* 0 is not a valid ID */
-FAST_MUTEX     LpcpLock; /* global internal sync in LPC facility */
+POBJECT_TYPE LpcPortObjectType;
+ULONG LpcpMaxMessageSize;
+PAGED_LOOKASIDE_LIST LpcpMessagesLookaside;
+KGUARDED_MUTEX LpcpLock;
+ULONG LpcpTraceLevel = LPC_CLOSE_DEBUG;
+ULONG LpcpNextMessageId = 1, LpcpNextCallbackId = 1;
 
 static GENERIC_MAPPING LpcpPortMapping = 
 {
@@ -33,105 +30,60 @@ static GENERIC_MAPPING LpcpPortMapping =
     PORT_ALL_ACCESS
 };
 
-/* FUNCTIONS *****************************************************************/
-
+/* PRIVATE FUNCTIONS *********************************************************/
 
 NTSTATUS
 INIT_FUNCTION
 NTAPI
-LpcpInitSystem (VOID)
+LpcpInitSystem(VOID)
 {
     OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
     UNICODE_STRING Name;
 
-    DPRINT("Creating Port Object Type\n");
-  
+    /* Setup the LPC Lock */
+    KeInitializeGuardedMutex(&LpcpLock);
+
     /* Create the Port Object Type */
     RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
     RtlInitUnicodeString(&Name, L"Port");
     ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
-    ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(EPORT);
+    ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(LPCP_PORT_OBJECT);
+    ObjectTypeInitializer.DefaultPagedPoolCharge = sizeof(LPCP_NONPAGED_PORT_QUEUE);
     ObjectTypeInitializer.GenericMapping = LpcpPortMapping;
-    ObjectTypeInitializer.PoolType = NonPagedPool;
+    ObjectTypeInitializer.PoolType = PagedPool;
     ObjectTypeInitializer.UseDefaultObject = TRUE;
     ObjectTypeInitializer.CloseProcedure = LpcpClosePort;
     ObjectTypeInitializer.DeleteProcedure = LpcpDeletePort;
     ObjectTypeInitializer.ValidAccessMask = PORT_ALL_ACCESS;
-    ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &LpcPortObjectType);
-
-    LpcpNextMessageId = 0;
-    ExInitializeFastMutex (& LpcpLock);
-
-    return(STATUS_SUCCESS);
-}
-
-
-/**********************************************************************
- * NAME                                                        INTERNAL
- *     NiInitializePort/3
- *
- * DESCRIPTION
- *     Initialize the EPORT object attributes. The Port
- *     object enters the inactive state.
- *
- * ARGUMENTS
- *     Port    Pointer to an EPORT object to initialize.
- *     Type    connect (RQST), or communication port (COMM)
- *     Parent  OPTIONAL connect port a communication port
- *             is created from
- *
- * RETURN VALUE
- *     STATUS_SUCCESS if initialization succedeed. An error code
- *     otherwise.
- */
-NTSTATUS STDCALL
-LpcpInitializePort (IN OUT  PEPORT Port,
-                 IN      USHORT Type,
-                 IN      PEPORT Parent OPTIONAL)
-{
-  if ((Type != EPORT_TYPE_SERVER_RQST_PORT) &&
-      (Type != EPORT_TYPE_SERVER_COMM_PORT) &&
-      (Type != EPORT_TYPE_CLIENT_COMM_PORT))
-  {
-         return STATUS_INVALID_PARAMETER_2;
-  }
-  memset (Port, 0, sizeof(EPORT));
-  KeInitializeSpinLock (& Port->Lock);
-  KeInitializeSemaphore( &Port->Semaphore, 0, MAXLONG );
-  Port->RequestPort = Parent;
-  Port->OtherPort = NULL;
-  Port->QueueLength = 0;
-  Port->ConnectQueueLength = 0;
-  Port->Type = Type;
-  Port->State = EPORT_INACTIVE;
-  InitializeListHead (& Port->QueueListHead);
-  InitializeListHead (& Port->ConnectQueueListHead);
-
-  return (STATUS_SUCCESS);
+    ObjectTypeInitializer.MaintainTypeList = TRUE;
+    ObCreateObjectType(&Name,
+                       &ObjectTypeInitializer,
+                       NULL,
+                       &LpcPortObjectType);
+
+    /* Allocate the LPC lookaside list */
+    LpcpMaxMessageSize = LPCP_MAX_MESSAGE_SIZE;
+    ExInitializePagedLookasideList(&LpcpMessagesLookaside,
+                                   NULL,
+                                   NULL,
+                                   0,
+                                   LpcpMaxMessageSize,
+                                   TAG('L', 'p', 'c', 'M'),
+                                   32);
+
+    /* We're done */
+    return STATUS_SUCCESS;
 }
 
+/* PUBLIC FUNCTIONS **********************************************************/
 
-/* MISCELLANEA SYSTEM SERVICES */
-
-
-/**********************************************************************
- * NAME                                                        SYSTEM
- *     NtImpersonateClientOfPort/2
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- *     PortHandle,
- *     ClientMessage
- *
- * RETURN VALUE
- */
-NTSTATUS STDCALL
-NtImpersonateClientOfPort (HANDLE              PortHandle,
-                          PPORT_MESSAGE        ClientMessage)
+NTSTATUS
+NTAPI
+NtImpersonateClientOfPort(IN HANDLE PortHandle,
+                          IN PPORT_MESSAGE ClientMessage)
 {
-  UNIMPLEMENTED;
-  return(STATUS_NOT_IMPLEMENTED);
+    UNIMPLEMENTED;
+    return STATUS_NOT_IMPLEMENTED;
 }
 
 NTSTATUS
@@ -142,4 +94,16 @@ NtQueryPortInformationProcess(VOID)
     return STATUS_UNSUCCESSFUL;
 }
 
+NTSTATUS
+NTAPI
+NtQueryInformationPort(IN HANDLE PortHandle,
+                       IN PORT_INFORMATION_CLASS PortInformationClass,
+                       OUT PVOID PortInformation,
+                       IN ULONG PortInformationLength,
+                       OUT PULONG ReturnLength)
+{
+    UNIMPLEMENTED;
+    return STATUS_NOT_IMPLEMENTED;
+}
+
 /* EOF */
diff --git a/reactos/ntoskrnl/lpc/query.c b/reactos/ntoskrnl/lpc/query.c
deleted file mode 100644 (file)
index 3463047..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/* $Id$
- *
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS kernel
- * FILE:            ntoskrnl/lpc/query.c
- * PURPOSE:         Communication mechanism
- *
- * PROGRAMMERS:     David Welch (welch@cwcom.net)
- */
-
-/* INCLUDES *****************************************************************/
-
-#include <ntoskrnl.h>
-#define NDEBUG
-#include <internal/debug.h>
-
-/* FUNCTIONS *****************************************************************/
-
-/**********************************************************************
- * NAME                                                        EXPORTED
- *     NtQueryInformationPort@20
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- *     PortHandle              [IN]
- *     PortInformationClass    [IN]
- *     PortInformation         [OUT]
- *     PortInformationLength   [IN]
- *     ReturnLength            [OUT]
- *
- * RETURN VALUE
- *     STATUS_SUCCESS if the call succedeed. An error code
- *     otherwise.
- *
- * NOTES
- *     P. Dabak reports that this system service seems to return
- *     no information.
- */
-/*EXPORTED*/ NTSTATUS STDCALL
-NtQueryInformationPort (IN     HANDLE  PortHandle,
-                       IN      PORT_INFORMATION_CLASS  PortInformationClass,
-                       OUT     PVOID   PortInformation,
-                       IN      ULONG   PortInformationLength,
-                       OUT     PULONG  ReturnLength)
-{
-  NTSTATUS     Status;
-  PEPORT               Port;
-
-  Status = ObReferenceObjectByHandle (PortHandle,
-                                     PORT_ALL_ACCESS,   /* AccessRequired */
-                                     LpcPortObjectType,
-                                     UserMode,
-                                     (PVOID *) & Port,
-                                     NULL);
-  if (!NT_SUCCESS(Status))
-    {
-      DPRINT("NtQueryInformationPort() = %x\n", Status);
-      return (Status);
-    }
-  /*
-   * FIXME: NT does nothing here!
-   */
-  ObDereferenceObject (Port);
-  return STATUS_SUCCESS;
-}
-
-
-/* EOF */
diff --git a/reactos/ntoskrnl/lpc/queue.c b/reactos/ntoskrnl/lpc/queue.c
deleted file mode 100644 (file)
index 971e108..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/* $Id$
- *
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS kernel
- * FILE:            ntoskrnl/lpc/queue.c
- * PURPOSE:         Communication mechanism
- *
- * PROGRAMMERS:     David Welch (welch@cwcom.net)
- */
-
-/* INCLUDES *****************************************************************/
-
-#include <ntoskrnl.h>
-#define NDEBUG
-#include <internal/debug.h>
-
-/* FUNCTIONS *****************************************************************/
-
-VOID STDCALL
-EiEnqueueMessagePort (IN OUT   PEPORT          Port,
-                     IN        PQUEUEDMESSAGE  Message)
-{
-  InsertTailList (&Port->QueueListHead,
-                 &Message->QueueListEntry);
-  Port->QueueLength++;
-}
-
-VOID STDCALL
-EiEnqueueMessageAtHeadPort (IN OUT     PEPORT          Port,
-                           IN  PQUEUEDMESSAGE  Message)
-{
-  InsertTailList (&Port->QueueListHead,
-                 &Message->QueueListEntry);
-  Port->QueueLength++;
-}
-
-PQUEUEDMESSAGE STDCALL
-EiDequeueMessagePort (IN OUT   PEPORT  Port)
-{
-  PQUEUEDMESSAGE       Message;
-  PLIST_ENTRY  entry;
-
-  if (IsListEmpty(&Port->QueueListHead))
-    {
-      return(NULL);
-    }
-  entry = RemoveHeadList (&Port->QueueListHead);
-  Message = CONTAINING_RECORD (entry, QUEUEDMESSAGE, QueueListEntry);
-  Port->QueueLength--;
-
-  return (Message);
-}
-
-
-VOID STDCALL
-EiEnqueueConnectMessagePort (IN OUT    PEPORT          Port,
-                            IN PQUEUEDMESSAGE  Message)
-{
-  InsertTailList (&Port->ConnectQueueListHead,
-                 &Message->QueueListEntry);
-  Port->ConnectQueueLength++;
-}
-
-
-PQUEUEDMESSAGE STDCALL
-EiDequeueConnectMessagePort (IN OUT    PEPORT  Port)
-{
-  PQUEUEDMESSAGE       Message;
-  PLIST_ENTRY  entry;
-
-  if (IsListEmpty(&Port->ConnectQueueListHead))
-    {
-      return(NULL);
-    }
-  entry = RemoveHeadList (&Port->ConnectQueueListHead);
-  Message = CONTAINING_RECORD (entry, QUEUEDMESSAGE, QueueListEntry);
-  Port->ConnectQueueLength--;
-
-  return (Message);
-}
-
-
-/* EOF */
diff --git a/reactos/ntoskrnl/lpc/receive.c b/reactos/ntoskrnl/lpc/receive.c
deleted file mode 100644 (file)
index 83631aa..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/* $Id$
- *
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS kernel
- * FILE:            ntoskrnl/lpc/receive.c
- * PURPOSE:         Communication mechanism
- *
- * PROGRAMMERS:     David Welch (welch@cwcom.net)
- */
-
-/* INCLUDES *****************************************************************/
-
-#include <ntoskrnl.h>
-#define NDEBUG
-#include <internal/debug.h>
-
-/* FUNCTIONS *****************************************************************/
-
-/**********************************************************************
- * NAME                                                        SYSTEM
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- *
- * RETURN VALUE
- */
-NTSTATUS STDCALL
-NtReadRequestData (HANDLE              PortHandle,
-                  PPORT_MESSAGE        Message,
-                  ULONG                Index,
-                  PVOID                Buffer,
-                  ULONG                BufferLength,
-                  PULONG               Returnlength)
-{
-       UNIMPLEMENTED;
-       return(STATUS_NOT_IMPLEMENTED);
-}
-
-
-/* EOF */
index 5fb58c2..311002e 100644 (file)
-/* $Id$
- *
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS kernel
+/*
+ * PROJECT:         ReactOS Kernel
+ * LICENSE:         GPL - See COPYING in the top level directory
  * FILE:            ntoskrnl/lpc/reply.c
- * PURPOSE:         Communication mechanism
- *
- * PROGRAMMERS:     David Welch (welch@cwcom.net)
+ * PURPOSE:         Local Procedure Call: Receive (Replies)
+ * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
  */
 
 /* INCLUDES ******************************************************************/
 
 #include <ntoskrnl.h>
+#include "lpc.h"
 #define NDEBUG
 #include <internal/debug.h>
 
-/* GLOBALS *******************************************************************/
+/* PRIVATE FUNCTIONS *********************************************************/
 
-/* FUNCTIONS *****************************************************************/
+VOID
+NTAPI
+LpcpFreeDataInfoMessage(IN PLPCP_PORT_OBJECT Port,
+                        IN ULONG MessageId,
+                        IN ULONG CallbackId)
+{
+    PLPCP_MESSAGE Message;
+    PLIST_ENTRY ListHead, NextEntry;
+
+    /* Check if the port we want is the connection port */
+    if ((Port->Flags & LPCP_PORT_TYPE_MASK) > LPCP_UNCONNECTED_PORT)
+    {
+        /* Use it */
+        Port = Port->ConnectionPort;
+    }
+
+    /* Loop the list */
+    ListHead = &Port->LpcDataInfoChainHead;
+    NextEntry = ListHead->Flink;
+    while (ListHead != NextEntry)
+    {
+        /* Get the message */
+        Message = CONTAINING_RECORD(NextEntry, LPCP_MESSAGE, Entry);
+
+        /* Make sure it matches */
+        if ((Message->Request.MessageId == MessageId) &&
+            (Message->Request.CallbackId == CallbackId))
+        {
+            /* Unlink and free it */
+            RemoveEntryList(&Message->Entry);
+            InitializeListHead(&Message->Entry);
+            LpcpFreeToPortZone(Message, TRUE);
+            break;
+        }
+
+        /* Go to the next entry */
+        NextEntry = NextEntry->Flink;
+    }
+}
 
-/**********************************************************************
- * NAME
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- *
- * RETURN VALUE
- *
- * REVISIONS
- */
-NTSTATUS STDCALL
-EiReplyOrRequestPort (IN       PEPORT          Port,
-                     IN        PPORT_MESSAGE   LpcReply,
-                     IN        ULONG           MessageType,
-                     IN        PEPORT          Sender)
+VOID
+NTAPI
+LpcpSaveDataInfoMessage(IN PLPCP_PORT_OBJECT Port,
+                        IN PLPCP_MESSAGE Message)
 {
-   KIRQL oldIrql;
-   PQUEUEDMESSAGE MessageReply;
-   ULONG Size;
-
-   if (Port == NULL)
-     {
-       KEBUGCHECK(0);
-     }
-
-   Size = sizeof(QUEUEDMESSAGE);
-   if (LpcReply && LpcReply->u1.s1.TotalLength > (CSHORT)sizeof(PORT_MESSAGE))
-     {
-       Size += LpcReply->u1.s1.TotalLength - sizeof(PORT_MESSAGE);
-     }
-   MessageReply = ExAllocatePoolWithTag(NonPagedPool, Size, 
-                                       TAG_LPC_MESSAGE);
-   MessageReply->Sender = Sender;
-
-   if (LpcReply != NULL)
-     {
-       memcpy(&MessageReply->Message, LpcReply, LpcReply->u1.s1.TotalLength);
-     }
-   else
-     {
-       MessageReply->Message.u1.s1.TotalLength = sizeof(PORT_MESSAGE);
-       MessageReply->Message.u1.s1.DataLength = 0;
-     }
-
-   MessageReply->Message.ClientId.UniqueProcess = PsGetCurrentProcessId();
-   MessageReply->Message.ClientId.UniqueThread = PsGetCurrentThreadId();
-   MessageReply->Message.u2.s2.Type = (CSHORT)MessageType;
-   MessageReply->Message.MessageId = InterlockedIncrementUL(&LpcpNextMessageId);
-
-   KeAcquireSpinLock(&Port->Lock, &oldIrql);
-   EiEnqueueMessagePort(Port, MessageReply);
-   KeReleaseSpinLock(&Port->Lock, oldIrql);
-
-   return(STATUS_SUCCESS);
+    PAGED_CODE();
+
+    /* Acquire the lock */
+    KeAcquireGuardedMutex(&LpcpLock);
+
+    /* Check if the port we want is the connection port */
+    if ((Port->Flags & LPCP_PORT_TYPE_MASK) > LPCP_UNCONNECTED_PORT)
+    {
+        /* Use it */
+        Port = Port->ConnectionPort;
+    }
+
+    /* Link the message */
+    InsertTailList(&Port->LpcDataInfoChainHead, &Message->Entry);
+
+    /* Release the lock */
+    KeReleaseGuardedMutex(&LpcpLock);
 }
 
+VOID
+NTAPI
+LpcpMoveMessage(IN PPORT_MESSAGE Destination,
+                IN PPORT_MESSAGE Origin,
+                IN PVOID Data,
+                IN ULONG MessageType,
+                IN PCLIENT_ID ClientId)
+{
+    /* Set the Message size */
+    LPCTRACE((LPC_REPLY_DEBUG | LPC_SEND_DEBUG),
+             "Destination/Origin: %p/%p. Data: %p. Length: %lx\n",
+             Destination,
+             Origin,
+             Data,
+             Origin->u1.Length);
+    Destination->u1.Length = Origin->u1.Length;
+
+    /* Set the Message Type */
+    Destination->u2.s2.Type = !MessageType ?
+                              Origin->u2.s2.Type : MessageType & 0xFFFF;
+
+    /* Check if we have a Client ID */
+    if (ClientId)
+    {
+        /* Set the Client ID */
+        Destination->ClientId.UniqueProcess = ClientId->UniqueProcess;
+        Destination->ClientId.UniqueThread = ClientId->UniqueThread;
+    }
+    else
+    {
+        /* Otherwise, copy it */
+        Destination->ClientId.UniqueProcess = Origin->ClientId.UniqueProcess;
+        Destination->ClientId.UniqueThread = Origin->ClientId.UniqueThread;
+    }
+
+    /* Copy the MessageId and ClientViewSize */
+    Destination->MessageId = Origin->MessageId;
+    Destination->ClientViewSize = Origin->ClientViewSize;
+
+    /* Copy the Message Data */
+    RtlMoveMemory(Destination + 1,
+                  Data,
+                  ((Destination->u1.Length & 0xFFFF) + 3) &~3);
+}
+
+/* PUBLIC FUNCTIONS **********************************************************/
 
-/**********************************************************************
- * NAME                                                        EXPORTED
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- *
- * RETURN VALUE
- *
- * REVISIONS
+/*
+ * @unimplemented
  */
-NTSTATUS STDCALL
-NtReplyPort (IN        HANDLE          PortHandle,
-            IN PPORT_MESSAGE   LpcReply)
+NTSTATUS
+NTAPI
+NtReplyPort(IN HANDLE PortHandle,
+            IN PPORT_MESSAGE LpcReply)
 {
-   NTSTATUS Status;
-   PEPORT Port;
-
-   DPRINT("NtReplyPort(PortHandle %x, LpcReply %x)\n", PortHandle, LpcReply);
-
-   Status = ObReferenceObjectByHandle(PortHandle,
-                                     PORT_ALL_ACCESS,   /* AccessRequired */
-                                     LpcPortObjectType,
-                                     UserMode,
-                                     (PVOID*)&Port,
-                                     NULL);
-   if (!NT_SUCCESS(Status))
-     {
-       DPRINT("NtReplyPort() = %x\n", Status);
-       return(Status);
-     }
-
-   if (EPORT_DISCONNECTED == Port->State)
-     {
-       ObDereferenceObject(Port);
-       return STATUS_PORT_DISCONNECTED;
-     }
-
-   Status = EiReplyOrRequestPort(Port->OtherPort,
-                                LpcReply,
-                                LPC_REPLY,
-                                Port);
-   KeReleaseSemaphore(&Port->OtherPort->Semaphore, IO_NO_INCREMENT, 1, FALSE);
-
-   ObDereferenceObject(Port);
-
-   return(Status);
+    UNIMPLEMENTED;
+    return STATUS_NOT_IMPLEMENTED;
 }
 
-
-/**********************************************************************
- * NAME                                                        EXPORTED
- *     NtReplyWaitReceivePortEx
- *
- * DESCRIPTION
- *     Can be used with waitable ports.
- *     Present only in w2k+.
- *
- * ARGUMENTS
- *     PortHandle
- *     PortId
- *     LpcReply
- *     LpcMessage
- *     Timeout
- *
- * RETURN VALUE
- *
- * REVISIONS
+/*
+ * @implemented
  */
-NTSTATUS STDCALL
+NTSTATUS
+NTAPI
 NtReplyWaitReceivePortEx(IN HANDLE PortHandle,
                          OUT PVOID *PortContext OPTIONAL,
                          IN PPORT_MESSAGE ReplyMessage OPTIONAL,
                          OUT PPORT_MESSAGE ReceiveMessage,
-                                    IN PLARGE_INTEGER Timeout OPTIONAL)
+                         IN PLARGE_INTEGER Timeout OPTIONAL)
 {
-   PEPORT Port;
-   KIRQL oldIrql;
-   PQUEUEDMESSAGE Request;
-   BOOLEAN Disconnected;
-   LARGE_INTEGER to;
-   KPROCESSOR_MODE PreviousMode;
-   NTSTATUS Status = STATUS_SUCCESS;
-   
-   PreviousMode = ExGetPreviousMode();
-
-   DPRINT("NtReplyWaitReceivePortEx(PortHandle %x, LpcReply %x, "
-         "LpcMessage %x)\n", PortHandle, ReplyMessage, ReceiveMessage);
-
-   if (PreviousMode != KernelMode)
-     {
-       _SEH_TRY
-         {
-           ProbeForWrite(ReceiveMessage,
-                         sizeof(PORT_MESSAGE),
-                         1);
-         }
-       _SEH_HANDLE
-         {
-           Status = _SEH_GetExceptionCode();
-         }
-       _SEH_END;
-       
-       if (!NT_SUCCESS(Status))
-         {
-           return Status;
-         }
-     }
-
-   Status = ObReferenceObjectByHandle(PortHandle,
-                                     PORT_ALL_ACCESS,
-                                     LpcPortObjectType,
-                                     UserMode,
-                                     (PVOID*)&Port,
-                                     NULL);
-   if (!NT_SUCCESS(Status))
-     {
-       DPRINT1("NtReplyWaitReceivePortEx() = %x\n", Status);
-       return(Status);
-     }
-   if( Port->State == EPORT_DISCONNECTED )
-     {
-       /* If the port is disconnected, force the timeout to be 0
-        * so we don't wait for new messages, because there won't be
-        * any, only try to remove any existing messages
-       */
-       Disconnected = TRUE;
-       to.QuadPart = 0;
-       Timeout = &to;
-     }
-   else Disconnected = FALSE;
-
-   /*
-    * Send the reply, only if port is connected
-    */
-   if (ReplyMessage != NULL && !Disconnected)
-     {
-       Status = EiReplyOrRequestPort(Port->OtherPort,
-                                     ReplyMessage,
-                                     LPC_REPLY,
-                                     Port);
-       KeReleaseSemaphore(&Port->OtherPort->Semaphore, IO_NO_INCREMENT, 1,
-                          FALSE);
-
-       if (!NT_SUCCESS(Status))
-         {
-            ObDereferenceObject(Port);
-            DPRINT1("NtReplyWaitReceivePortEx() = %x\n", Status);
-            return(Status);
-         }
-     }
-
-   /*
-    * Want for a message to be received
-    */
-   Status = KeWaitForSingleObject(&Port->Semaphore,
-                                 UserRequest,
-                                 UserMode,
-                                 FALSE,
-                                 Timeout);
-   if( Status == STATUS_TIMEOUT )
-     {
-       /*
-       * if the port is disconnected, and there are no remaining messages,
-        * return STATUS_PORT_DISCONNECTED
-       */
-       ObDereferenceObject(Port);
-       return(Disconnected ? STATUS_PORT_DISCONNECTED : STATUS_TIMEOUT);
-     }
-
-   if (!NT_SUCCESS(Status))
-     {
-       if (STATUS_THREAD_IS_TERMINATING != Status)
-        {
-          DPRINT1("NtReplyWaitReceivePortEx() = %x\n", Status);
-        }
-       ObDereferenceObject(Port);
-       return(Status);
-     }
-
-   /*
-    * Dequeue the message
-    */
-   KeAcquireSpinLock(&Port->Lock, &oldIrql);
-   Request = EiDequeueMessagePort(Port);
-   KeReleaseSpinLock(&Port->Lock, oldIrql);
-
-   if (Request == NULL)
-     {
-       ObDereferenceObject(Port);
-       return STATUS_UNSUCCESSFUL;
-     }
-
-   if (Request->Message.u2.s2.Type == LPC_CONNECTION_REQUEST)
-     {
-       PORT_MESSAGE Header;
-       PEPORT_CONNECT_REQUEST_MESSAGE CRequest;
-
-       CRequest = (PEPORT_CONNECT_REQUEST_MESSAGE)&Request->Message;
-       memcpy(&Header, &Request->Message, sizeof(PORT_MESSAGE));
-       Header.u1.s1.DataLength = (CSHORT)CRequest->ConnectDataLength;
-       Header.u1.s1.TotalLength = Header.u1.s1.DataLength + sizeof(PORT_MESSAGE);
-       
-       if (PreviousMode != KernelMode)
-         {
-           _SEH_TRY
-             {
-               ProbeForWrite((PVOID)(ReceiveMessage + 1),
-                             CRequest->ConnectDataLength,
-                             1);
-
-               RtlCopyMemory(ReceiveMessage,
-                             &Header,
-                             sizeof(PORT_MESSAGE));
-               RtlCopyMemory((PVOID)(ReceiveMessage + 1),
-                             CRequest->ConnectData,
-                             CRequest->ConnectDataLength);
-             }
-           _SEH_HANDLE
-             {
-               Status = _SEH_GetExceptionCode();
-             }
-           _SEH_END;
-         }
-       else
-         {
-           RtlCopyMemory(ReceiveMessage,
-                         &Header,
-                         sizeof(PORT_MESSAGE));
-           RtlCopyMemory((PVOID)(ReceiveMessage + 1),
-                         CRequest->ConnectData,
-                         CRequest->ConnectDataLength);
-         }
-     }
-   else
-     {
-       if (PreviousMode != KernelMode)
-         {
-           _SEH_TRY
-             {
-               ProbeForWrite(ReceiveMessage,
-                             Request->Message.u1.s1.TotalLength,
-                             1);
-
-               RtlCopyMemory(ReceiveMessage,
-                             &Request->Message,
-                             Request->Message.u1.s1.TotalLength);
-             }
-           _SEH_HANDLE
-             {
-               Status = _SEH_GetExceptionCode();
-             }
-           _SEH_END;
-         }
-       else
-         {
-           RtlCopyMemory(ReceiveMessage,
-                         &Request->Message,
-                         Request->Message.u1.s1.TotalLength);
-         }
-     }
-   if (!NT_SUCCESS(Status))
-     {
-       /*
-       * Copying the message to the caller's buffer failed so
-       * undo what we did and return.
-       * FIXME: Also increment semaphore.
-       */
-       KeAcquireSpinLock(&Port->Lock, &oldIrql);
-       EiEnqueueMessageAtHeadPort(Port, Request);
-       KeReleaseSpinLock(&Port->Lock, oldIrql);
-       ObDereferenceObject(Port);
-       return(Status);
-     }
-   if (Request->Message.u2.s2.Type == LPC_CONNECTION_REQUEST)
-     {
-       KeAcquireSpinLock(&Port->Lock, &oldIrql);
-       EiEnqueueConnectMessagePort(Port, Request);
-       KeReleaseSpinLock(&Port->Lock, oldIrql);
-     }
-   else
-     {
-       ExFreePool(Request);
-     }
-
-   /*
-    * Dereference the port
-    */
-   ObDereferenceObject(Port);
-   return(STATUS_SUCCESS);
+    PLPCP_PORT_OBJECT Port, ReceivePort;
+    KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(), WaitMode = PreviousMode;
+    NTSTATUS Status;
+    PLPCP_MESSAGE Message;
+    PETHREAD Thread = PsGetCurrentThread(), WakeupThread;
+    PLPCP_CONNECTION_MESSAGE ConnectMessage;
+    ULONG ConnectionInfoLength;
+    PAGED_CODE();
+    LPCTRACE(LPC_REPLY_DEBUG,
+             "Handle: %lx. Messages: %p/%p. Context: %p\n",
+             PortHandle,
+             ReplyMessage,
+             ReceiveMessage,
+             PortContext);
+
+    /* If this is a system thread, then let it page out its stack */
+    if (Thread->SystemThread) WaitMode = UserMode;
+
+    /* Check if caller has a reply message */
+    if (ReplyMessage)
+    {
+        /* Validate its length */
+        if ((ReplyMessage->u1.s1.DataLength + sizeof(PORT_MESSAGE)) >
+            ReplyMessage->u1.s1.TotalLength)
+        {
+            /* Fail */
+            return STATUS_INVALID_PARAMETER;
+        }
+
+        /* Make sure it has a valid ID */
+        if (!ReplyMessage->MessageId) return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Get the Port object */
+    Status = ObReferenceObjectByHandle(PortHandle,
+                                       0,
+                                       LpcPortObjectType,
+                                       PreviousMode,
+                                       (PVOID*)&Port,
+                                       NULL);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    /* Check if the caller has a reply message */
+    if (ReplyMessage)
+    {
+        /* Validate its length in respect to the port object */
+        if ((ReplyMessage->u1.s1.TotalLength > Port->MaxMessageLength) ||
+            (ReplyMessage->u1.s1.TotalLength <= ReplyMessage->u1.s1.DataLength))
+        {
+            /* Too large, fail */
+            ObDereferenceObject(Port);
+            return STATUS_PORT_MESSAGE_TOO_LONG;
+        }
+    }
+
+    /* Check if this is anything but a client port */
+    if ((Port->Flags & LPCP_PORT_TYPE_MASK) != LPCP_CLIENT_PORT)
+    {
+        /* Use the connection port */
+        ReceivePort = Port->ConnectionPort;
+    }
+    else
+    {
+        /* Otherwise, use the port itself */
+        ReceivePort = Port;
+    }
+
+    /* Check if the caller gave a reply message */
+    if (ReplyMessage)
+    {
+        /* Get the ETHREAD corresponding to it */
+        Status = PsLookupProcessThreadByCid(&ReplyMessage->ClientId,
+                                            NULL,
+                                            &WakeupThread);
+        if (!NT_SUCCESS(Status))
+        {
+            /* No thread found, fail */
+            ObDereferenceObject(Port);
+            return Status;
+        }
+
+        /* Allocate a message from the port zone */
+        Message = LpcpAllocateFromPortZone();
+        if (!Message)
+        {
+            /* Fail if we couldn't allocate a message */
+            ObDereferenceObject(WakeupThread);
+            ObDereferenceObject(Port);
+            return STATUS_NO_MEMORY;
+        }
+
+        /* Keep the lock acquired */
+        KeAcquireGuardedMutex(&LpcpLock);
+
+        /* Make sure this is the reply the thread is waiting for */
+        if (WakeupThread->LpcReplyMessageId != ReplyMessage->MessageId)
+        {
+            /* It isn't, fail */
+            LpcpFreeToPortZone(Message, TRUE);
+            KeReleaseGuardedMutex(&LpcpLock);
+            ObDereferenceObject(WakeupThread);
+            ObDereferenceObject(Port);
+            return STATUS_REPLY_MESSAGE_MISMATCH;
+        }
+
+        /* Copy the message */
+        LpcpMoveMessage(&Message->Request,
+                        ReplyMessage,
+                        ReplyMessage + 1,
+                        LPC_REPLY,
+                        NULL);
+
+        /* Free any data information */
+        LpcpFreeDataInfoMessage(Port,
+                                ReplyMessage->MessageId,
+                                ReplyMessage->CallbackId);
+
+        /* Reference the thread while we use it */
+        ObReferenceObject(WakeupThread);
+        Message->RepliedToThread = WakeupThread;
+
+        /* Set this as the reply message */
+        WakeupThread->LpcReplyMessageId = 0;
+        WakeupThread->LpcReplyMessage = (PVOID)Message;
+
+        /* Check if we have messages on the reply chain */
+        if (!(WakeupThread->LpcExitThreadCalled) &&
+            !(IsListEmpty(&WakeupThread->LpcReplyChain)))
+        {
+            /* Remove us from it and reinitialize it */
+            RemoveEntryList(&WakeupThread->LpcReplyChain);
+            InitializeListHead(&WakeupThread->LpcReplyChain);
+        }
+
+        /* Check if this is the message the thread had received */
+        if ((Thread->LpcReceivedMsgIdValid) &&
+            (Thread->LpcReceivedMessageId == ReplyMessage->MessageId))
+        {
+            /* Clear this data */
+            Thread->LpcReceivedMessageId = 0;
+            Thread->LpcReceivedMsgIdValid = FALSE;
+        }
+
+        /* Release the lock and release the LPC semaphore to wake up waiters */
+        KeReleaseGuardedMutex(&LpcpLock);
+        LpcpCompleteWait(&WakeupThread->LpcReplySemaphore);
+
+        /* Now we can let go of the thread */
+        ObDereferenceObject(WakeupThread);
+    }
+
+    /* Now wait for someone to reply to us */
+    LpcpReceiveWait(ReceivePort->MsgQueue.Semaphore, WaitMode);
+    if (Status != STATUS_SUCCESS) goto Cleanup;
+
+    /* Wait done, get the LPC lock */
+    KeAcquireGuardedMutex(&LpcpLock);
+
+    /* Check if we've received nothing */
+    if (IsListEmpty(&ReceivePort->MsgQueue.ReceiveHead))
+    {
+        /* Check if this was a waitable port and wake it */
+        if (ReceivePort->Flags & LPCP_WAITABLE_PORT)
+        {
+            /* Reset its event */
+            KeResetEvent(&ReceivePort->WaitEvent);
+        }
+
+        /* Release the lock and fail */
+        KeReleaseGuardedMutex(&LpcpLock);
+        ObDereferenceObject(Port);
+        return STATUS_UNSUCCESSFUL;
+    }
+
+    /* Get the message on the queue */
+    Message = CONTAINING_RECORD(RemoveHeadList(&ReceivePort->
+                                               MsgQueue.ReceiveHead),
+                                LPCP_MESSAGE,
+                                Entry);
+
+    /* Check if the queue is empty now */
+    if (IsListEmpty(&ReceivePort->MsgQueue.ReceiveHead))
+    {
+        /* Check if this was a waitable port */
+        if (ReceivePort->Flags & LPCP_WAITABLE_PORT)
+        {
+            /* Reset its event */
+            KeResetEvent(&ReceivePort->WaitEvent);
+        }
+    }
+
+    /* Re-initialize the message's list entry */
+    InitializeListHead(&Message->Entry);
+
+    /* Set this as the received message */
+    Thread->LpcReceivedMessageId = Message->Request.MessageId;
+    Thread->LpcReceivedMsgIdValid = TRUE;
+
+    /* Done touching global data, release the lock */
+    KeReleaseGuardedMutex(&LpcpLock);
+
+    /* Check if this was a connection request */
+    if (LpcpGetMessageType(&Message->Request) == LPC_CONNECTION_REQUEST)
+    {
+        /* Get the connection message */
+        ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(Message + 1);
+        LPCTRACE(LPC_REPLY_DEBUG,
+                 "Request Messages: %p/%p\n",
+                 Message,
+                 ConnectMessage);
+
+        /* Get its length */
+        ConnectionInfoLength = Message->Request.u1.s1.DataLength -
+                               sizeof(LPCP_CONNECTION_MESSAGE);
+
+        /* Return it as the receive message */
+        *ReceiveMessage = Message->Request;
+
+        /* Clear our stack variable so the message doesn't get freed */
+        Message = NULL;
+
+        /* Setup the receive message */
+        ReceiveMessage->u1.s1.TotalLength = sizeof(LPCP_MESSAGE) +
+                                            ConnectionInfoLength;
+        ReceiveMessage->u1.s1.DataLength = ConnectionInfoLength;
+        RtlMoveMemory(ReceiveMessage + 1,
+                      ConnectMessage + 1,
+                      ConnectionInfoLength);
+
+        /* Clear the port context if the caller requested one */
+        if (PortContext) *PortContext = NULL;
+    }
+    else if (Message->Request.u2.s2.Type != LPC_REPLY)
+    {
+        /* Otherwise, this is a new message or event */
+        LPCTRACE(LPC_REPLY_DEBUG,
+                 "Non-Reply Messages: %p/%p\n",
+                 &Message->Request,
+                 (&Message->Request) + 1);
+
+        /* Copy it */
+        LpcpMoveMessage(ReceiveMessage,
+                        &Message->Request,
+                        (&Message->Request) + 1,
+                        0,
+                        NULL);
+
+        /* Return its context */
+        if (PortContext) *PortContext = Message->PortContext;
+
+        /* And check if it has data information */
+        if (Message->Request.u2.s2.DataInfoOffset)
+        {
+            /* It does, save it, and don't free the message below */
+            LpcpSaveDataInfoMessage(Port, Message);
+            Message = NULL;
+        }
+    }
+    else
+    {
+        /* This is a reply message, should never happen! */
+        ASSERT(FALSE);
+    }
+
+    /* If we have a message pointer here, free it */
+    if (Message) LpcpFreeToPortZone(Message, FALSE);
+
+Cleanup:
+    /* All done, dereference the port and return the status */
+    LPCTRACE(LPC_REPLY_DEBUG,
+             "Port: %p. Status: %p\n",
+             Port,
+             Status);
+    ObDereferenceObject(Port);
+    return Status;
 }
 
-
-/**********************************************************************
- * NAME                                                EXPORTED
- *     NtReplyWaitReceivePort
- *
- * DESCRIPTION
- *     Can be used with waitable ports.
- *
- * ARGUMENTS
- *     PortHandle
- *     PortId
- *     LpcReply
- *     LpcMessage
- *
- * RETURN VALUE
- *
- * REVISIONS
+/*
+ * @implemented
  */
-NTSTATUS STDCALL
+NTSTATUS
+NTAPI
 NtReplyWaitReceivePort(IN HANDLE PortHandle,
                        OUT PVOID *PortContext OPTIONAL,
                        IN PPORT_MESSAGE ReplyMessage OPTIONAL,
                        OUT PPORT_MESSAGE ReceiveMessage)
 {
+    /* Call the newer API */
     return NtReplyWaitReceivePortEx(PortHandle,
-                                                   PortContext,
-                                                   ReplyMessage,
-                                                   ReceiveMessage,
-                                                   NULL);
+                                    PortContext,
+                                    ReplyMessage,
+                                    ReceiveMessage,
+                                    NULL);
 }
 
-/**********************************************************************
- * NAME
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- *
- * RETURN VALUE
- *
- * REVISIONS
+/*
+ * @unimplemented
  */
-NTSTATUS STDCALL
-NtReplyWaitReplyPort (HANDLE           PortHandle,
-                     PPORT_MESSAGE     ReplyMessage)
+NTSTATUS
+NTAPI
+NtReplyWaitReplyPort(IN HANDLE PortHandle,
+                     IN PPORT_MESSAGE ReplyMessage)
 {
-   UNIMPLEMENTED;
-   return(STATUS_NOT_IMPLEMENTED);
+    UNIMPLEMENTED;
+    return STATUS_NOT_IMPLEMENTED;
 }
 
 /*
- * @implemented
+ * @unimplemented
  */
 NTSTATUS
 NTAPI
-LpcRequestWaitReplyPort(IN PVOID Port,
-                        IN PPORT_MESSAGE LpcMessageRequest,
-                        OUT PPORT_MESSAGE LpcMessageReply)
+NtReadRequestData(IN HANDLE PortHandle,
+                  IN PPORT_MESSAGE Message,
+                  IN ULONG Index,
+                  IN PVOID Buffer,
+                  IN ULONG BufferLength,
+                  OUT PULONG Returnlength)
 {
-    HANDLE PortHandle;
-    NTSTATUS Status;
-    UNICODE_STRING PortName;
-    ULONG ConnectInfoLength;
-
-    //
-    // OMG HAXX!
-    //
-    RtlInitUnicodeString(&PortName, L"\\Windows\\ApiPort");
-    ConnectInfoLength = 0;
-    Status = ZwConnectPort(&PortHandle,
-                           &PortName,
-                           NULL,
-                           NULL,
-                           NULL,
-                           NULL,
-                           NULL,
-                           &ConnectInfoLength);
-
-    Status = ZwRequestWaitReplyPort(PortHandle,
-                                    LpcMessageRequest,
-                                    LpcMessageReply);
-
-    /* Close the handle */
-    ObCloseHandle(PortHandle, KernelMode);
-    return Status;
+    UNIMPLEMENTED;
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+/*
+ * @unimplemented
+ */
+NTSTATUS
+NTAPI
+NtWriteRequestData(IN HANDLE PortHandle,
+                   IN PPORT_MESSAGE Message,
+                   IN ULONG Index,
+                   IN PVOID Buffer,
+                   IN ULONG BufferLength,
+                   OUT PULONG ReturnLength)
+{
+    UNIMPLEMENTED;
+    return STATUS_NOT_IMPLEMENTED;
 }
 
 /* EOF */
index 1dc522f..f49e0a6 100644 (file)
-/* $Id$
- *
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS kernel
+/*
+ * PROJECT:         ReactOS Kernel
+ * LICENSE:         GPL - See COPYING in the top level directory
  * FILE:            ntoskrnl/lpc/send.c
- * PURPOSE:         Communication mechanism
- *
- * PROGRAMMERS:     David Welch (welch@cwcom.net)
+ * PURPOSE:         Local Procedure Call: Sending (Requests)
+ * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
  */
 
-/* INCLUDES *****************************************************************/
+/* INCLUDES ******************************************************************/
 
 #include <ntoskrnl.h>
-
+#include "lpc.h"
 #define NDEBUG
 #include <internal/debug.h>
 
-/**********************************************************************
- * NAME
- *     LpcRequestPort/2
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- *
- * 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.
- *
+/* PUBLIC FUNCTIONS **********************************************************/
+
+/*
  * @implemented
  */
-NTSTATUS STDCALL LpcRequestPort (IN    PVOID           PortObject,
-                                IN     PPORT_MESSAGE   LpcMessage)
+NTSTATUS
+NTAPI
+LpcRequestPort(IN PVOID PortObject,
+               IN PPORT_MESSAGE LpcMessage)
 {
-   NTSTATUS Status;
-   PEPORT Port = (PEPORT)PortObject;
-
-   DPRINT("LpcRequestPort(PortHandle %08x, LpcMessage %08x)\n", Port, LpcMessage);
-
-#ifdef __USE_NT_LPC__
-   /* Check the message's type */
-   if (LPC_NEW_MESSAGE == LpcMessage->u2.s2.Type)
-   {
-      LpcMessage->u2.s2.Type = LPC_DATAGRAM;
-   }
-   else if (LPC_DATAGRAM == LpcMessage->u2.s2.Type)
-   {
-      return STATUS_INVALID_PARAMETER;
-   }
-   else if (LpcMessage->u2.s2.Type > 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,
-                                Port);
-   KeReleaseSemaphore( &Port->Semaphore, IO_NO_INCREMENT, 1, FALSE );
-
-   return(Status);
+    PLPCP_PORT_OBJECT Port = (PLPCP_PORT_OBJECT)PortObject, QueuePort;
+    ULONG MessageType;
+    PLPCP_MESSAGE Message;
+    KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
+    PAGED_CODE();
+    LPCTRACE(LPC_SEND_DEBUG, "Port: %p. Message: %p\n", Port, LpcMessage);
+
+    /* Check if this is a non-datagram message */
+    if (LpcMessage->u2.s2.Type)
+    {
+        /* Get the message type */
+        MessageType = LpcpGetMessageType(LpcMessage);
+
+        /* Validate it */
+        if ((MessageType < LPC_DATAGRAM) || (MessageType > LPC_CLIENT_DIED))
+        {
+            /* Fail */
+            return STATUS_INVALID_PARAMETER;
+        }
+
+        /* Mark this as a kernel-mode message only if we really came from there */
+        if ((PreviousMode == KernelMode) &&
+            (LpcMessage->u2.s2.Type & LPC_KERNELMODE_MESSAGE))
+        {
+            /* We did, this is a kernel mode message */
+            MessageType |= LPC_KERNELMODE_MESSAGE;
+        }
+    }
+    else
+    {
+        /* This is a datagram */
+        MessageType = LPC_DATAGRAM;
+    }
+
+    /* Can't have data information on this type of call */
+    if (LpcMessage->u2.s2.DataInfoOffset) return STATUS_INVALID_PARAMETER;
+
+    /* Validate message sizes */
+    if ((LpcMessage->u1.s1.TotalLength > Port->MaxMessageLength) ||
+        (LpcMessage->u1.s1.TotalLength <= LpcMessage->u1.s1.DataLength))
+    {
+        /* Fail */
+        return STATUS_PORT_MESSAGE_TOO_LONG;
+    }
+
+    /* Allocate a new message */
+    Message = LpcpAllocateFromPortZone();
+    if (!Message) return STATUS_NO_MEMORY;
+
+    /* Clear the context */
+    Message->PortContext = NULL;
+
+    /* Copy the message */
+    LpcpMoveMessage(&Message->Request,
+                    LpcMessage,
+                    LpcMessage + 1,
+                    MessageType,
+                    &PsGetCurrentThread()->Cid);
+
+    /* Acquire the LPC lock */
+    KeAcquireGuardedMutex(&LpcpLock);
+
+    /* Check if this is anything but a connection port */
+    if ((Port->Flags & LPCP_PORT_TYPE_MASK) != LPCP_CONNECTION_PORT)
+    {
+        /* The queue port is the connected port */
+        QueuePort = Port->ConnectedPort;
+        if (QueuePort)
+        {
+            /* Check if this is a client port */
+            if ((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_CLIENT_PORT)
+            {
+                /* Then copy the context */
+                Message->PortContext = QueuePort->PortContext;
+                QueuePort = Port->ConnectionPort;
+            }
+            else if ((Port->Flags & LPCP_PORT_TYPE_MASK) != LPCP_COMMUNICATION_PORT)
+            {
+                /* Any other kind of port, use the connection port */
+                QueuePort = Port->ConnectionPort;
+            }
+        }
+    }
+    else
+    {
+        /* For connection ports, use the port itself */
+        QueuePort = PortObject;
+    }
+
+    /* Make sure we have a port */
+    if (QueuePort)
+    {
+        /* Generate the Message ID and set it */
+        Message->Request.MessageId =  LpcpNextMessageId++;
+        if (!LpcpNextMessageId) LpcpNextMessageId = 1;
+        Message->Request.CallbackId = 0;
+
+        /* No Message ID for the thread */
+        PsGetCurrentThread()->LpcReplyMessageId = 0;
+
+        /* Insert the message in our chain */
+        InsertTailList(&QueuePort->MsgQueue.ReceiveHead, &Message->Entry);
+
+        /* Release the lock and release the semaphore */
+        KeReleaseGuardedMutex(&LpcpLock);
+        LpcpCompleteWait(QueuePort->MsgQueue.Semaphore);
+
+        /* If this is a waitable port, wake it up */
+        if (QueuePort->Flags & LPCP_WAITABLE_PORT)
+        {
+            /* Wake it */
+            KeSetEvent(&QueuePort->WaitEvent, IO_NO_INCREMENT, FALSE);
+        }
+
+        /* We're done */
+        LPCTRACE(LPC_SEND_DEBUG, "Port: %p. Message: %p\n", QueuePort, Message);
+        return STATUS_SUCCESS;
+    }
+
+    /* If we got here, then free the message and fail */
+    LpcpFreeToPortZone(Message, TRUE);
+    KeReleaseGuardedMutex(&LpcpLock);
+    return STATUS_PORT_DISCONNECTED;
 }
 
+/*
+* @unimplemented
+*/
+NTSTATUS
+NTAPI
+LpcRequestWaitReplyPort(IN PVOID Port,
+                        IN PPORT_MESSAGE LpcMessageRequest,
+                        OUT PPORT_MESSAGE LpcMessageReply)
+{
+    UNIMPLEMENTED;
+    return STATUS_NOT_IMPLEMENTED;
+}
 
-/**********************************************************************
- * NAME
- *     NtRequestPort/2
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- *
- * RETURN VALUE
- *
- * REVISIONS
- *
- * @implemented
+/*
+ * @unimplemented
  */
-NTSTATUS STDCALL NtRequestPort (IN     HANDLE          PortHandle,
-                               IN      PPORT_MESSAGE   LpcMessage)
+NTSTATUS
+NTAPI
+NtRequestPort(IN HANDLE PortHandle,
+              IN PPORT_MESSAGE LpcMessage)
 {
-   NTSTATUS Status;
-   PEPORT Port;
-
-   DPRINT("NtRequestPort(PortHandle %x LpcMessage %x)\n", PortHandle,
-         LpcMessage);
-
-   Status = ObReferenceObjectByHandle(PortHandle,
-                                     PORT_ALL_ACCESS,
-                                     LpcPortObjectType,
-                                     UserMode,
-                                     (PVOID*)&Port,
-                                     NULL);
-   if (!NT_SUCCESS(Status))
-     {
-       DPRINT("NtRequestPort() = %x\n", Status);
-       return(Status);
-     }
-
-   Status = LpcRequestPort(Port->OtherPort,
-                          LpcMessage);
-
-   ObDereferenceObject(Port);
-   return(Status);
+    UNIMPLEMENTED;
+    return STATUS_NOT_IMPLEMENTED;
 }
 
-
-/**********************************************************************
- * NAME
- *     NtRequestWaitReplyPort/3
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- *
- * RETURN VALUE
- *
- * REVISIONS
- *
+/*
  * @implemented
  */
-NTSTATUS STDCALL
-NtRequestWaitReplyPort (IN HANDLE PortHandle,
-                       PPORT_MESSAGE UnsafeLpcRequest,
-                       PPORT_MESSAGE UnsafeLpcReply)
+NTSTATUS
+NTAPI
+NtRequestWaitReplyPort(IN HANDLE PortHandle,
+                       IN PPORT_MESSAGE LpcRequest,
+                       IN OUT PPORT_MESSAGE LpcReply)
 {
-   PETHREAD CurrentThread;
-   struct _KPROCESS *AttachedProcess;
-   PEPORT Port;
-   PQUEUEDMESSAGE Message;
-   KIRQL oldIrql;
-   PPORT_MESSAGE LpcRequest;
-   USHORT LpcRequestMessageSize = 0, LpcRequestDataSize = 0;
-   KPROCESSOR_MODE PreviousMode;
-   NTSTATUS Status = STATUS_SUCCESS;
-   
-   PreviousMode = ExGetPreviousMode();
-   
-   if (PreviousMode != KernelMode)
-     {
-       _SEH_TRY
-         {
-           ProbeForRead(UnsafeLpcRequest,
-                        sizeof(PORT_MESSAGE),
-                        1);
-           ProbeForWrite(UnsafeLpcReply,
-                         sizeof(PORT_MESSAGE),
-                         1);
-           LpcRequestMessageSize = UnsafeLpcRequest->u1.s1.TotalLength;
-         }
-       _SEH_HANDLE
-         {
-           Status = _SEH_GetExceptionCode();
-         }
-       _SEH_END;
-       
-       if (!NT_SUCCESS(Status))
-         {
-           return Status;
-         }
-     }
-   else
-     {
-       LpcRequestMessageSize = UnsafeLpcRequest->u1.s1.TotalLength;
-     }
-
-   DPRINT("NtRequestWaitReplyPort(PortHandle %x, LpcRequest %x, "
-         "LpcReply %x)\n", PortHandle, UnsafeLpcRequest, UnsafeLpcReply);
-
-   Status = ObReferenceObjectByHandle(PortHandle,
-                                     PORT_ALL_ACCESS,
-                                     LpcPortObjectType,
-                                     UserMode,
-                                     (PVOID*)&Port,
-                                     NULL);
-   if (!NT_SUCCESS(Status))
-     {
-       return(Status);
-     }
-
-   if (EPORT_DISCONNECTED == Port->State)
-     {
-       ObDereferenceObject(Port);
-       return STATUS_PORT_DISCONNECTED;
-     }
-
-   /* win32k sometimes needs to KeAttach() the CSRSS process in order to make
-      the PortHandle valid. Now that we've got the EPORT structure from the
-      handle we can undo this, so everything is normal again. Need to
-      re-KeAttach() before returning though */
-   CurrentThread = PsGetCurrentThread();
-   if (&CurrentThread->ThreadsProcess->Pcb == CurrentThread->Tcb.ApcState.Process)
-     {
-       AttachedProcess = NULL;
-     }
-   else
-     {
-       AttachedProcess = CurrentThread->Tcb.ApcState.Process;
-       KeDetachProcess();
-     }
-
-   if (LpcRequestMessageSize > LPC_MAX_MESSAGE_LENGTH)
-     {
-       if (NULL != AttachedProcess)
-         {
-           KeAttachProcess(AttachedProcess);
-         }
-       ObDereferenceObject(Port);
-       return(STATUS_PORT_MESSAGE_TOO_LONG);
-     }
-   LpcRequest = ExAllocatePool(NonPagedPool, LpcRequestMessageSize);
-   if (LpcRequest == NULL)
-     {
-       if (NULL != AttachedProcess)
-         {
-           KeAttachProcess(AttachedProcess);
-         }
-       ObDereferenceObject(Port);
-       return(STATUS_NO_MEMORY);
-     }
-   if (PreviousMode != KernelMode)
-     {
-       _SEH_TRY
-         {
-           RtlCopyMemory(LpcRequest,
-                         UnsafeLpcRequest,
-                         LpcRequestMessageSize);
-           LpcRequestMessageSize = LpcRequest->u1.s1.TotalLength;
-           LpcRequestDataSize = LpcRequest->u1.s1.DataLength;
-         }
-       _SEH_HANDLE
-         {
-           Status = _SEH_GetExceptionCode();
-         }
-       _SEH_END;
-       
-       if (!NT_SUCCESS(Status))
-         {
-           ExFreePool(LpcRequest);
-           if (NULL != AttachedProcess)
-             {
-               KeAttachProcess(AttachedProcess);
-             }
-           ObDereferenceObject(Port);
-           return(Status);
-         }
-     }
-   else
-     {
-       RtlCopyMemory(LpcRequest,
-                     UnsafeLpcRequest,
-                     LpcRequestMessageSize);
-       LpcRequestMessageSize = LpcRequest->u1.s1.TotalLength;
-       LpcRequestDataSize = LpcRequest->u1.s1.DataLength;
-     }
-
-   if (LpcRequestMessageSize > LPC_MAX_MESSAGE_LENGTH)
-     {
-       ExFreePool(LpcRequest);
-       if (NULL != AttachedProcess)
-         {
-           KeAttachProcess(AttachedProcess);
-         }
-       ObDereferenceObject(Port);
-       return(STATUS_PORT_MESSAGE_TOO_LONG);
-     }
-   if (LpcRequestDataSize > LPC_MAX_DATA_LENGTH)
-     {
-       ExFreePool(LpcRequest);
-       if (NULL != AttachedProcess)
-         {
-           KeAttachProcess(AttachedProcess);
-         }
-       ObDereferenceObject(Port);
-       return(STATUS_PORT_MESSAGE_TOO_LONG);
-     }
-
-   Status = EiReplyOrRequestPort(Port->OtherPort,
-                                LpcRequest,
-                 LpcRequest->u2.s2.Type == LPC_ERROR_EVENT ? LPC_ERROR_EVENT : LPC_REQUEST,
-                                Port);
-   if (!NT_SUCCESS(Status))
-     {
-       DPRINT1("Enqueue failed\n");
-       ExFreePool(LpcRequest);
-        if (NULL != AttachedProcess)
-          {
-            KeAttachProcess(AttachedProcess);
-          }
-       ObDereferenceObject(Port);
-       return(Status);
-     }
-   ExFreePool(LpcRequest);
-   KeReleaseSemaphore (&Port->OtherPort->Semaphore, IO_NO_INCREMENT,
-                      1, FALSE);
-
-   /*
-    * Wait for a reply
-    */
-   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.u1.s1.TotalLength %d\n",
-                 Message->Message.u1.s1.TotalLength);
-           if (PreviousMode != KernelMode)
-             {
-               _SEH_TRY
-                 {
-                   RtlCopyMemory(UnsafeLpcReply,
-                                 &Message->Message,
-                                 Message->Message.u1.s1.TotalLength);
-                 }
-               _SEH_HANDLE
-                 {
-                   Status = _SEH_GetExceptionCode();
-                 }
-               _SEH_END;
-             }
-           else
-             {
-               RtlCopyMemory(UnsafeLpcReply,
-                             &Message->Message,
-                             Message->Message.u1.s1.TotalLength);
-             }
-           ExFreePool(Message);
-         }
-       else
-         Status = STATUS_UNSUCCESSFUL;
-     }
-   else
-     {
-       if (NT_SUCCESS(Status))
-         {
-          Status = STATUS_UNSUCCESSFUL;
-        }
-     }
-   if (NULL != AttachedProcess)
-     {
-       KeAttachProcess(AttachedProcess);
-     }
-   ObDereferenceObject(Port);
-
-   return(Status);
-}
+    PLPCP_PORT_OBJECT Port, QueuePort, ReplyPort;
+    KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
+    NTSTATUS Status;
+    PLPCP_MESSAGE Message;
+    PETHREAD Thread = PsGetCurrentThread();
+    BOOLEAN Callback;
+    PKSEMAPHORE Semaphore;
+    ULONG MessageType;
+    PAGED_CODE();
+    LPCTRACE(LPC_SEND_DEBUG,
+             "Handle: %lx. Messages: %p/%p. Type: %lx\n",
+             PortHandle,
+             LpcRequest,
+             LpcReply,
+             LpcpGetMessageType(LpcRequest));
 
+    /* Check if the thread is dying */
+    if (Thread->LpcExitThreadCalled) return STATUS_THREAD_IS_TERMINATING;
 
-/**********************************************************************
- * NAME
- *     NtWriteRequestData/6
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- *
- * RETURN VALUE
- *
- * REVISIONS
- */
-NTSTATUS STDCALL NtWriteRequestData (HANDLE            PortHandle,
-                                    PPORT_MESSAGE      Message,
-                                    ULONG              Index,
-                                    PVOID              Buffer,
-                                    ULONG              BufferLength,
-                                    PULONG             ReturnLength)
-{
-   UNIMPLEMENTED;
-   return(STATUS_NOT_IMPLEMENTED);
-}
+    /* Check if this is an LPC Request */
+    if (LpcpGetMessageType(LpcRequest) == LPC_REQUEST)
+    {
+        /* Then it's a callback */
+        Callback = TRUE;
+    }
+    else if (LpcpGetMessageType(LpcRequest))
+    {
+        /* This is a not kernel-mode message */
+        return STATUS_INVALID_PARAMETER;
+    }
+    else
+    {
+        /* This is a kernel-mode message without a callback */
+        LpcRequest->u2.s2.Type |= LPC_REQUEST;
+        Callback = FALSE;
+    }
 
+    /* Get the message type */
+    MessageType = LpcRequest->u2.s2.Type;
+
+    /* Validate the length */
+    if ((LpcRequest->u1.s1.DataLength + sizeof(PORT_MESSAGE)) >
+         LpcRequest->u1.s1.TotalLength)
+    {
+        /* Fail */
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Reference the object */
+    Status = ObReferenceObjectByHandle(PortHandle,
+                                       0,
+                                       LpcPortObjectType,
+                                       PreviousMode,
+                                       (PVOID*)&Port,
+                                       NULL);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    /* Validate the message length */
+    if ((LpcRequest->u1.s1.TotalLength > Port->MaxMessageLength) ||
+        (LpcRequest->u1.s1.TotalLength <= LpcRequest->u1.s1.DataLength))
+    {
+        /* Fail */
+        ObDereferenceObject(Port);
+        return STATUS_PORT_MESSAGE_TOO_LONG;
+    }
+
+    /* Allocate a message from the port zone */
+    Message = LpcpAllocateFromPortZone();
+    if (!Message)
+    {
+        /* Fail if we couldn't allocate a message */
+        ObDereferenceObject(Port);
+        return STATUS_NO_MEMORY;
+    }
+
+    /* Check if this is a callback */
+    if (Callback)
+    {
+        /* FIXME: TODO */
+        Semaphore = NULL; // we'd use the Thread Semaphore here
+        ASSERT(FALSE);
+    }
+    else
+    {
+        /* No callback, just copy the message */
+        LpcpMoveMessage(&Message->Request,
+                        LpcRequest,
+                        LpcRequest + 1,
+                        MessageType,
+                        &Thread->Cid);
+
+        /* Acquire the LPC lock */
+        KeAcquireGuardedMutex(&LpcpLock);
+
+        /* Right now clear the port context */
+        Message->PortContext = NULL;
+
+        /* Check if this is a not connection port */
+        if ((Port->Flags & LPCP_PORT_TYPE_MASK) != LPCP_CONNECTION_PORT)
+        {
+            /* We want the connected port */
+            QueuePort = Port->ConnectedPort;
+            if (!QueuePort)
+            {
+                /* We have no connected port, fail */
+                LpcpFreeToPortZone(Message, TRUE);
+                KeReleaseGuardedMutex(&LpcpLock);
+                ObDereferenceObject(Port);
+                return STATUS_PORT_DISCONNECTED;
+            }
+
+            /* This will be the rundown port */
+            ReplyPort = QueuePort;
+
+            /* Check if this is a communication port */
+            if ((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_CLIENT_PORT)
+            {
+                /* Copy the port context and use the connection port */
+                Message->PortContext = ReplyPort->PortContext;
+                QueuePort = Port->ConnectionPort;
+            }
+            else if ((Port->Flags & LPCP_PORT_TYPE_MASK) !=
+                      LPCP_COMMUNICATION_PORT)
+            {
+                /* Use the connection port for anything but communication ports */
+                QueuePort = Port->ConnectionPort;
+            }
+        }
+        else
+        {
+            /* Otherwise, for a connection port, use the same port object */
+            QueuePort = ReplyPort = Port;
+        }
+
+        /* No reply thread */
+        Message->RepliedToThread = NULL;
+
+        /* Generate the Message ID and set it */
+        Message->Request.MessageId =  LpcpNextMessageId++;
+        if (!LpcpNextMessageId) LpcpNextMessageId = 1;
+        Message->Request.CallbackId = 0;
+
+        /* Set the message ID for our thread now */
+        Thread->LpcReplyMessageId = Message->Request.MessageId;
+        Thread->LpcReplyMessage = NULL;
+
+        /* Insert the message in our chain */
+        InsertTailList(&QueuePort->MsgQueue.ReceiveHead, &Message->Entry);
+        InsertTailList(&ReplyPort->LpcReplyChainHead, &Thread->LpcReplyChain);
+
+        /* Release the lock and get the semaphore we'll use later */
+        KeReleaseGuardedMutex(&LpcpLock);
+        Semaphore = QueuePort->MsgQueue.Semaphore;
+
+        /* If this is a waitable port, wake it up */
+        if (QueuePort->Flags & LPCP_WAITABLE_PORT)
+        {
+            /* Wake it */
+            KeSetEvent(&QueuePort->WaitEvent, IO_NO_INCREMENT, FALSE);
+        }
+    }
+
+    /* Now release the semaphore */
+    LpcpCompleteWait(Semaphore);
+
+    /* And let's wait for the reply */
+    LpcpReplyWait(&Thread->LpcReplySemaphore, PreviousMode);
+
+    /* Acquire the LPC lock */
+    KeAcquireGuardedMutex(&LpcpLock);
+
+    /* Get the LPC Message and clear our thread's reply data */
+    Message = Thread->LpcReplyMessage;
+    Thread->LpcReplyMessage = NULL;
+    Thread->LpcReplyMessageId = 0;
+
+    /* Check if we have anything on the reply chain*/
+    if (!IsListEmpty(&Thread->LpcReplyChain))
+    {
+        /* Remove this thread and reinitialize the list */
+        RemoveEntryList(&Thread->LpcReplyChain);
+        InitializeListHead(&Thread->LpcReplyChain);
+    }
+
+    /* Release the lock */
+    KeReleaseGuardedMutex(&LpcpLock);
+
+    /* Check if we got a reply */
+    if (Status == STATUS_SUCCESS)
+    {
+        /* Check if we have a valid message */
+        if (Message)
+        {
+            LPCTRACE(LPC_SEND_DEBUG,
+                     "Reply Messages: %p/%p\n",
+                     &Message->Request,
+                     (&Message->Request) + 1);
+
+            /* Move the message */
+            LpcpMoveMessage(LpcReply,
+                            &Message->Request,
+                            (&Message->Request) + 1,
+                            0,
+                            NULL);
+
+            /* Check if this is an LPC request with data information */
+            if ((LpcpGetMessageType(&Message->Request) == LPC_REQUEST) &&
+                (Message->Request.u2.s2.DataInfoOffset))
+            {
+                /* Save the data information */
+                LpcpSaveDataInfoMessage(Port, Message);
+            }
+            else
+            {
+                /* Otherwise, just free it */
+                LpcpFreeToPortZone(Message, FALSE);
+            }
+        }
+        else
+        {
+            /* We don't have a reply */
+            Status = STATUS_LPC_REPLY_LOST;
+        }
+    }
+    else
+    {
+        /* The wait failed, free the message while holding the lock */
+        KeAcquireGuardedMutex(&LpcpLock);
+        LpcpFreeToPortZone(Message, TRUE);
+        KeReleaseGuardedMutex(&LpcpLock);
+    }
+
+    /* All done */
+    LPCTRACE(LPC_SEND_DEBUG,
+             "Port: %p. Status: %p\n",
+             Port,
+             Status);
+    ObDereferenceObject(Port);
+    return Status;
+}
 
 /* EOF */
index 10c6ed3..dd73ec5 100644 (file)
@@ -9,9 +9,6 @@
     <define name="__NO_CTYPE_INLINES" />
     <define name="__USE_W32API" />
     <define name="WIN9X_COMPAT_SPINLOCK" />
-    <if property="NTLPC" value="1">
-        <define name="NTLPC" />
-    </if>
     <include base="cmlib">.</include>
     <include base="ntoskrnl">include</include>
     <include base="ReactOS">include/reactos/drivers</include>
             <file>loader.c</file>
             <file>rtl.c</file>
     </directory>
-    <if property="NTLPC" value="0">
-        <directory name="lpc">
-                <file>close.c</file>
-                <file>complete.c</file>
-                <file>connect.c</file>
-                <file>create.c</file>
-                <file>listen.c</file>
-                <file>port.c</file>
-                <file>query.c</file>
-                <file>queue.c</file>
-                <file>receive.c</file>
-                <file>reply.c</file>
-                <file>send.c</file>
-        </directory>
-    </if>
-    <if property="NTLPC" value="1">
-        <directory name="lpc">
-            <directory name="ntlpc">
-                <file>close.c</file>
-                <file>complete.c</file>
-                <file>connect.c</file>
-                <file>create.c</file>
-                <file>listen.c</file>
-                <file>port.c</file>
-                <file>reply.c</file>
-                <file>send.c</file>
-            </directory>
-        </directory>
-    </if>
+    <directory name="lpc">
+            <file>close.c</file>
+            <file>complete.c</file>
+            <file>connect.c</file>
+            <file>create.c</file>
+            <file>listen.c</file>
+            <file>port.c</file>
+            <file>reply.c</file>
+            <file>send.c</file>
+    </directory>
     <directory name="mm">
         <if property="ARCH" value="i386">
             <directory name="i386">
index 34cd8ba..3622370 100644 (file)
@@ -1716,8 +1716,7 @@ ObpSetHandleAttributes(IN PHANDLE_TABLE HandleTable,
                        IN OUT PHANDLE_TABLE_ENTRY HandleTableEntry,
                        IN PVOID Context)
 {
-    POBP_SET_HANDLE_ATTRIBUTES_CONTEXT SetHandleInfo =
-        (POBP_SET_HANDLE_ATTRIBUTES_CONTEXT)Context;
+    POBP_SET_HANDLE_ATTRIBUTES_CONTEXT SetHandleInfo = Context;
     POBJECT_HEADER ObjectHeader = EX_HTE_TO_HDR(HandleTableEntry);
     PAGED_CODE();