Author: ion
Date: Sun Nov 5 23:31:35 2006
New Revision: 24685
URL:
http://svn.reactos.org/svn/reactos?rev=24685&view=rev
Log:
- Simplify LPC Message allocation with an LpcpAllocateFromPortZone macro.
- Move LPC Macros/inlines to lpc_x.h
- Implement LpcRequestPort.
- Fix a bug in CsrTerminateProcess which was setting up incorrect sizes for the LPC
message.
- Add some debug output to csrss.
- NTLPC works perfectly now, except for a bug on shutdown which doesn't properly close
LPC processes.
Added:
trunk/reactos/ntoskrnl/lpc/ntlpc/lpc_x.h
Modified:
trunk/reactos/ntoskrnl/lpc/ntlpc/close.c
trunk/reactos/ntoskrnl/lpc/ntlpc/connect.c
trunk/reactos/ntoskrnl/lpc/ntlpc/lpc.h
trunk/reactos/ntoskrnl/lpc/ntlpc/port.c
trunk/reactos/ntoskrnl/lpc/ntlpc/reply.c
trunk/reactos/ntoskrnl/lpc/ntlpc/send.c
trunk/reactos/subsystems/win32/csrss/api/process.c
trunk/reactos/subsystems/win32/csrss/api/wapi.c
Modified: trunk/reactos/ntoskrnl/lpc/ntlpc/close.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/lpc/ntlpc/close.c…
==============================================================================
--- trunk/reactos/ntoskrnl/lpc/ntlpc/close.c (original)
+++ trunk/reactos/ntoskrnl/lpc/ntlpc/close.c Sun Nov 5 23:31:35 2006
@@ -40,7 +40,7 @@
if (Message)
{
/* FIXME: TODO */
- ASSERT(FALSE);
+ KEBUGCHECK(0);
}
/* Release the lock */
Modified: trunk/reactos/ntoskrnl/lpc/ntlpc/connect.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/lpc/ntlpc/connect…
==============================================================================
--- trunk/reactos/ntoskrnl/lpc/ntlpc/connect.c (original)
+++ trunk/reactos/ntoskrnl/lpc/ntlpc/connect.c Sun Nov 5 23:31:35 2006
@@ -301,25 +301,15 @@
ConnectionInfoLength = Port->MaxConnectionInfoLength;
}
- /* Allocate a message from the port zone while holding the lock */
- KeAcquireGuardedMutex(&LpcpLock);
- Message = ExAllocateFromPagedLookasideList(&LpcpMessagesLookaside);
+ /* Allocate a message from the port zone */
+ Message = LpcpAllocateFromPortZone();
if (!Message)
{
/* Fail if we couldn't allocate a message */
- KeReleaseGuardedMutex(&LpcpLock);
if (SectionToMap) ObDereferenceObject(SectionToMap);
ObDereferenceObject(ClientPort);
return STATUS_NO_MEMORY;
}
-
- /* Initialize it */
- InitializeListHead(&Message->Entry);
- Message->RepliedToThread = NULL;
- Message->Request.u2.ZeroInit = 0;
-
- /* Release the lock */
- KeReleaseGuardedMutex(&LpcpLock);
/* Set pointer to the connection message and fill in the CID */
ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(Message + 1);
Modified: trunk/reactos/ntoskrnl/lpc/ntlpc/lpc.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/lpc/ntlpc/lpc.h?r…
==============================================================================
--- trunk/reactos/ntoskrnl/lpc/ntlpc/lpc.h (original)
+++ trunk/reactos/ntoskrnl/lpc/ntlpc/lpc.h Sun Nov 5 23:31:35 2006
@@ -46,97 +46,6 @@
}
#endif
#endif
-
-//
-// Gets the message type, removing the kernel-mode flag
-//
-#define LpcpGetMessageType(x) \
- ((x)->u2.s2.Type &~ LPCP_KERNEL_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); \
-}
-
-//
-// Internal flag used for Kernel LPC Messages
-//
-#define LPCP_KERNEL_MESSAGE 0x8000
//
// Internal Port Management
@@ -214,3 +123,8 @@
extern PAGED_LOOKASIDE_LIST LpcpMessagesLookaside;
extern ULONG LpcpMaxMessageSize;
extern ULONG LpcpTraceLevel;
+
+//
+// Inlined Functions
+//
+#include "lpc_x.h"
Added: trunk/reactos/ntoskrnl/lpc/ntlpc/lpc_x.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/lpc/ntlpc/lpc_x.h…
==============================================================================
--- trunk/reactos/ntoskrnl/lpc/ntlpc/lpc_x.h (added)
+++ trunk/reactos/ntoskrnl/lpc/ntlpc/lpc_x.h Sun Nov 5 23:31:35 2006
@@ -1,0 +1,122 @@
+/*
+* 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(a)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;
+}
Modified: trunk/reactos/ntoskrnl/lpc/ntlpc/port.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/lpc/ntlpc/port.c?…
==============================================================================
--- trunk/reactos/ntoskrnl/lpc/ntlpc/port.c (original)
+++ trunk/reactos/ntoskrnl/lpc/ntlpc/port.c Sun Nov 5 23:31:35 2006
@@ -19,7 +19,7 @@
ULONG LpcpMaxMessageSize;
PAGED_LOOKASIDE_LIST LpcpMessagesLookaside;
KGUARDED_MUTEX LpcpLock;
-ULONG LpcpTraceLevel = 0xFFFFFFFF;
+ULONG LpcpTraceLevel = LPC_CLOSE_DEBUG;
ULONG LpcpNextMessageId = 1, LpcpNextCallbackId = 1;
static GENERIC_MAPPING LpcpPortMapping =
Modified: trunk/reactos/ntoskrnl/lpc/ntlpc/reply.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/lpc/ntlpc/reply.c…
==============================================================================
--- trunk/reactos/ntoskrnl/lpc/ntlpc/reply.c (original)
+++ trunk/reactos/ntoskrnl/lpc/ntlpc/reply.c Sun Nov 5 23:31:35 2006
@@ -230,24 +230,18 @@
return Status;
}
- /* Acquire the LPC Lock */
- KeAcquireGuardedMutex(&LpcpLock);
-
- /* Allocate a new message */
- Message = ExAllocateFromPagedLookasideList(&LpcpMessagesLookaside);
+ /* Allocate a message from the port zone */
+ Message = LpcpAllocateFromPortZone();
if (!Message)
{
- /* Out of memory, fail */
- KeReleaseGuardedMutex(&LpcpLock);
+ /* Fail if we couldn't allocate a message */
ObDereferenceObject(WakeupThread);
ObDereferenceObject(Port);
return STATUS_NO_MEMORY;
}
- /* Initialize the header */
- InitializeListHead(&Message->Entry);
- Message->RepliedToThread = NULL;
- Message->Request.u2.ZeroInit = 0;
+ /* Keep the lock acquired */
+ KeAcquireGuardedMutex(&LpcpLock);
/* Make sure this is the reply the thread is waiting for */
if (WakeupThread->LpcReplyMessageId != ReplyMessage->MessageId)
@@ -284,7 +278,7 @@
if (!(WakeupThread->LpcExitThreadCalled) &&
!(IsListEmpty(&WakeupThread->LpcReplyChain)))
{
- /* Remove us from it and reinitiailize it */
+ /* Remove us from it and reinitialize it */
RemoveEntryList(&WakeupThread->LpcReplyChain);
InitializeListHead(&WakeupThread->LpcReplyChain);
}
Modified: trunk/reactos/ntoskrnl/lpc/ntlpc/send.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/lpc/ntlpc/send.c?…
==============================================================================
--- trunk/reactos/ntoskrnl/lpc/ntlpc/send.c (original)
+++ trunk/reactos/ntoskrnl/lpc/ntlpc/send.c Sun Nov 5 23:31:35 2006
@@ -16,15 +16,136 @@
/* PUBLIC FUNCTIONS **********************************************************/
/*
- * @unimplemented
+ * @implemented
*/
NTSTATUS
NTAPI
-LpcRequestPort(IN PVOID Port,
+LpcRequestPort(IN PVOID PortObject,
IN PPORT_MESSAGE LpcMessage)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ 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;
}
/*
@@ -127,17 +248,11 @@
return STATUS_PORT_MESSAGE_TOO_LONG;
}
- /* Acquire the lock */
- KeAcquireGuardedMutex(&LpcpLock);
-
- /* Allocate a message */
- Message = ExAllocateFromPagedLookasideList(&LpcpMessagesLookaside);
- KeReleaseGuardedMutex(&LpcpLock);
-
- /* Check if allocation worked */
+ /* Allocate a message from the port zone */
+ Message = LpcpAllocateFromPortZone();
if (!Message)
{
- /* Fail */
+ /* Fail if we couldn't allocate a message */
ObDereferenceObject(Port);
return STATUS_NO_MEMORY;
}
Modified: trunk/reactos/subsystems/win32/csrss/api/process.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/csrss/api…
==============================================================================
--- trunk/reactos/subsystems/win32/csrss/api/process.c (original)
+++ trunk/reactos/subsystems/win32/csrss/api/process.c Sun Nov 5 23:31:35 2006
@@ -260,8 +260,8 @@
CSR_API(CsrTerminateProcess)
{
- Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE) -
sizeof(PORT_MESSAGE);
- Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE);
+ Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
+ Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
if (ProcessData == NULL)
{
Modified: trunk/reactos/subsystems/win32/csrss/api/wapi.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/csrss/api…
==============================================================================
--- trunk/reactos/subsystems/win32/csrss/api/wapi.c (original)
+++ trunk/reactos/subsystems/win32/csrss/api/wapi.c Sun Nov 5 23:31:35 2006
@@ -72,9 +72,9 @@
unsigned DefIndex;
ULONG Type;
- DPRINT("CSR: Calling handler for type: %x.\n", Request->Type);
+ DPRINT1("CSR: Calling handler for type: %x.\n", Request->Type);
Type = Request->Type & 0xFFFF; /* FIXME: USE MACRO */
- DPRINT("CSR: API Number: %x ServerID: %x\n",Type, Request->Type >>
16);
+ DPRINT1("CSR: API Number: %x ServerID: %x\n",Type, Request->Type >>
16);
/* FIXME: Extract DefIndex instead of looping */
for (DefIndex = 0; ! Found && DefIndex < ApiDefinitionsCount; DefIndex++)
@@ -218,13 +218,14 @@
&Request->Header);
if (!NT_SUCCESS(Status))
{
- DPRINT1("NtReplyWaitReceivePort failed\n");
- break;
+ DPRINT1("NtReplyWaitReceivePort failed: %lx\n", Status);
+ break;
}
/* If the connection was closed, handle that */
if (Request->Header.u2.s2.Type == LPC_PORT_CLOSED)
{
+ DPRINT1("Port died, oh well\n");
CsrFreeProcessData( Request->Header.ClientId.UniqueProcess );
break;
}
@@ -236,9 +237,16 @@
continue;
}
+ if (Request->Header.u2.s2.Type == LPC_CLIENT_DIED)
+ {
+ DPRINT1("Clietn died, oh well\n");
+ Reply = NULL;
+ continue;
+ }
+
DPRINT("CSR: Got CSR API: %x [Message Origin: %x]\n",
- Request->Type,
- Request->Header.ClientId.UniqueProcess);
+ Request->Type,
+ Request->Header.ClientId.UniqueThread);
/* Get the Process Data */
ProcessData = CsrGetProcessData(Request->Header.ClientId.UniqueProcess);
@@ -252,7 +260,7 @@
if (ProcessData->Terminated)
{
DPRINT1("Message %d: process %d already terminated\n",
- Request->Type, (ULONG)Request->Header.ClientId.UniqueProcess);
+ Request->Type, (ULONG)Request->Header.ClientId.UniqueProcess);
continue;
}
@@ -271,7 +279,7 @@
/* Send back the reply */
Reply = Request;
}
-
+
/* Close the port and exit the thread */
NtClose(ServerPort);
RtlExitUserThread(STATUS_SUCCESS);