Author: ion
Date: Sun Jan 21 20:21:42 2007
New Revision: 25557
URL:
http://svn.reactos.org/svn/reactos?rev=25557&view=rev
Log:
- Fix multiple LPC race conditions.
- Improve LpcpFreeToPortZone calls for optimizing lock release.
- Use RtlCopyMemory instead of RtlMoveMemory to optimize data transfer speed.
- Always hold a reference to the connection port associated to the LPC port and properly
handle this reference in all the LPC code.
- Hold a reference to the process that mapped a server/client view, and use this field
when freeing memory in case we're called out-of-process.
- Fix a lot of list parsing loops and code to handle the case when the list is now empty.
- Validate more fields and data in the code.
- There are still some LPC bugs at system shutdown.
Modified:
trunk/reactos/ntoskrnl/include/internal/lpc_x.h
trunk/reactos/ntoskrnl/ke/gate.c
trunk/reactos/ntoskrnl/lpc/close.c
trunk/reactos/ntoskrnl/lpc/complete.c
trunk/reactos/ntoskrnl/lpc/connect.c
trunk/reactos/ntoskrnl/lpc/create.c
trunk/reactos/ntoskrnl/lpc/listen.c
trunk/reactos/ntoskrnl/lpc/port.c
trunk/reactos/ntoskrnl/lpc/reply.c
trunk/reactos/ntoskrnl/lpc/send.c
Modified: trunk/reactos/ntoskrnl/include/internal/lpc_x.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/lpc_x.h (original)
+++ trunk/reactos/ntoskrnl/include/internal/lpc_x.h Sun Jan 21 20:21:42 2007
@@ -45,7 +45,7 @@
{ \
/* It's still signaled, so wait on it */ \
KeWaitForSingleObject(s, \
- Executive, \
+ WrExecutive, \
KernelMode, \
FALSE, \
NULL); \
@@ -73,7 +73,7 @@
{ \
/* It's still signaled, so wait on it */ \
KeWaitForSingleObject(s, \
- Executive, \
+ WrExecutive, \
KernelMode, \
FALSE, \
NULL); \
Modified: trunk/reactos/ntoskrnl/ke/gate.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/gate.c?rev=255…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/gate.c (original)
+++ trunk/reactos/ntoskrnl/ke/gate.c Sun Jan 21 20:21:42 2007
@@ -137,7 +137,6 @@
KIRQL OldIrql;
ASSERT_GATE(Gate);
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
- ASSERT(FALSE);
/* Start entry loop */
for (;;)
Modified: trunk/reactos/ntoskrnl/lpc/close.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/lpc/close.c?rev=2…
==============================================================================
--- trunk/reactos/ntoskrnl/lpc/close.c (original)
+++ trunk/reactos/ntoskrnl/lpc/close.c Sun Jan 21 20:21:42 2007
@@ -19,6 +19,7 @@
LpcExitThread(IN PETHREAD Thread)
{
PLPCP_MESSAGE Message;
+ ASSERT(Thread == PsGetCurrentThread());
/* Acquire the lock */
KeAcquireGuardedMutex(&LpcpLock);
@@ -54,7 +55,7 @@
PLPCP_CONNECTION_MESSAGE ConnectMessage;
PLPCP_PORT_OBJECT ClientPort = NULL;
PETHREAD Thread = NULL;
- BOOLEAN LockHeld = Flags & 1;
+ BOOLEAN LockHeld = Flags & 1, ReleaseLock = Flags & 2;
PAGED_CODE();
LPCTRACE(LPC_CLOSE_DEBUG, "Message: %p. Flags: %lx\n", Message, Flags);
@@ -99,7 +100,7 @@
ExFreeToPagedLookasideList(&LpcpMessagesLookaside, Message);
/* Reacquire the lock if needed */
- if ((LockHeld) && !(Flags & 2)) KeAcquireGuardedMutex(&LpcpLock);
+ if ((LockHeld) && !(ReleaseLock)) KeAcquireGuardedMutex(&LpcpLock);
}
VOID
@@ -110,14 +111,27 @@
PLIST_ENTRY ListHead, NextEntry;
PETHREAD Thread;
PLPCP_MESSAGE Message;
+ PLPCP_PORT_OBJECT ConnectionPort = NULL;
PLPCP_CONNECTION_MESSAGE ConnectMessage;
+ PAGED_CODE();
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 we have a connected port */
+ if (((Port->Flags & LPCP_PORT_TYPE_MASK) != LPCP_UNCONNECTED_PORT) &&
+ (Port->ConnectedPort))
+ {
+ /* Disconnect it */
+ Port->ConnectedPort->ConnectedPort = NULL;
+ if (Port->ConnectedPort->ConnectionPort)
+ {
+ /* Save and clear connection port */
+ ConnectionPort = Port->ConnectedPort->ConnectionPort;
+ Port->ConnectedPort->ConnectionPort = NULL;
+ }
+ }
/* Check if this is a connection port */
if ((Port->Flags & LPCP_PORT_TYPE_MASK) == LPCP_CONNECTION_PORT)
@@ -129,7 +143,7 @@
/* Walk all the threads waiting and signal them */
ListHead = &Port->LpcReplyChainHead;
NextEntry = ListHead->Flink;
- while (NextEntry != ListHead)
+ while ((NextEntry) && (NextEntry != ListHead))
{
/* Get the Thread */
Thread = CONTAINING_RECORD(NextEntry, ETHREAD, LpcReplyChain);
@@ -147,57 +161,63 @@
/* Check if someone is waiting */
if (!KeReadStateSemaphore(&Thread->LpcReplySemaphore))
{
- /* Get the message and check if it's a connection request */
+ /* Get the message */
Message = Thread->LpcReplyMessage;
- if (Message->Request.u2.s2.Type == LPC_CONNECTION_REQUEST)
+ if (Message)
{
- /* Get the connection message */
- ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(Message + 1);
-
- /* Check if it had a section */
- if (ConnectMessage->SectionToMap)
+ /* Check if it's a connection request */
+ if (Message->Request.u2.s2.Type == LPC_CONNECTION_REQUEST)
{
- /* Dereference it */
- ObDereferenceObject(ConnectMessage->SectionToMap);
+ /* 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, 1);
+ NextEntry = Port->LpcReplyChainHead.Flink;
}
- /* 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);
+ /* Release the semaphore and reset message id count */
+ Thread->LpcReplyMessageId = 0;
+ KeReleaseSemaphore(&Thread->LpcReplySemaphore, 0, 1, FALSE);
+ }
}
/* Reinitialize the list head */
InitializeListHead(&Port->LpcReplyChainHead);
/* Loop queued messages */
- ListHead = &Port->MsgQueue.ReceiveHead;
- NextEntry = ListHead->Flink;
- while ((NextEntry) && (ListHead != NextEntry))
+ while ((Port->MsgQueue.ReceiveHead.Flink) &&
+ !(IsListEmpty (&Port->MsgQueue.ReceiveHead)))
{
/* Get the message */
- Message = CONTAINING_RECORD(NextEntry, LPCP_MESSAGE, Entry);
- NextEntry = NextEntry->Flink;
+ Message = CONTAINING_RECORD(Port->MsgQueue.ReceiveHead.Flink,
+ LPCP_MESSAGE,
+ Entry);
/* Free and reinitialize it's list head */
+ RemoveEntryList(&Message->Entry);
InitializeListHead(&Message->Entry);
/* Remove it from the port zone */
- LpcpFreeToPortZone(Message, TRUE);
- }
-
- /* Reinitialize the message queue list head */
- InitializeListHead(&Port->MsgQueue.ReceiveHead);
+ LpcpFreeToPortZone(Message, 1);
+ }
/* Release the lock */
KeReleaseGuardedMutex(&LpcpLock);
+
+ /* Dereference the connection port */
+ if (ConnectionPort) ObDereferenceObject(ConnectionPort);
/* Check if we have to free the port entirely */
if (Destroy)
@@ -334,13 +354,32 @@
/* 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);
+ /* Check if we had views */
+ if ((Port->ClientSectionBase) || (Port->ServerSectionBase))
+ {
+ /* Check if we had a client view */
+ if (Port->ClientSectionBase)
+ {
+ /* Unmap it */
+ MmUnmapViewOfSection(Port->MappingProcess,
+ Port->ClientSectionBase);
+ }
+
+ /* Check for a server view */
+ if (Port->ServerSectionBase)
+ {
+ /* Unmap it */
+ MmUnmapViewOfSection(Port->MappingProcess,
+ Port->ServerSectionBase);
+ }
+
+ /* Dereference the mapping process */
+ ObDereferenceObject(Port->MappingProcess);
+ Port->MappingProcess = NULL;
+ }
+
+ /* Acquire the lock */
+ KeAcquireGuardedMutex(&LpcpLock);
/* Get the connection port */
ConnectionPort = Port->ConnectionPort;
@@ -348,9 +387,6 @@
{
/* Get the PID */
Pid = PsGetCurrentProcessId();
-
- /* Acquire the lock */
- KeAcquireGuardedMutex(&LpcpLock);
/* Loop the data lists */
ListHead = &ConnectionPort->LpcDataInfoChainHead;
@@ -361,12 +397,29 @@
Message = CONTAINING_RECORD(NextEntry, LPCP_MESSAGE, Entry);
NextEntry = NextEntry->Flink;
- /* Check if the PID matches */
- if (Message->Request.ClientId.UniqueProcess == Pid)
+ /* Check if this is the connection port */
+ if (Port == ConnectionPort)
+ {
+ /* Free queued messages */
+ RemoveEntryList(&Message->Entry);
+ InitializeListHead(&Message->Entry);
+ LpcpFreeToPortZone(Message, 1);
+
+ /* Restart at the head */
+ NextEntry = ListHead->Flink;
+ }
+ else if ((Message->Request.ClientId.UniqueProcess == Pid) &&
+ ((Message->SenderPort == Port) ||
+ (Message->SenderPort == Port->ConnectedPort) ||
+ (Message->SenderPort == ConnectionPort)))
{
/* Remove it */
RemoveEntryList(&Message->Entry);
- LpcpFreeToPortZone(Message, TRUE);
+ InitializeListHead(&Message->Entry);
+ LpcpFreeToPortZone(Message, 1);
+
+ /* Restart at the head */
+ NextEntry = ListHead->Flink;
}
}
@@ -375,6 +428,11 @@
/* Dereference the object unless it's the same port */
if (ConnectionPort != Port) ObDereferenceObject(ConnectionPort);
+ }
+ else
+ {
+ /* Release the lock */
+ KeReleaseGuardedMutex(&LpcpLock);
}
/* Check if this is a connection port with a server process*/
Modified: trunk/reactos/ntoskrnl/lpc/complete.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/lpc/complete.c?re…
==============================================================================
--- trunk/reactos/ntoskrnl/lpc/complete.c (original)
+++ trunk/reactos/ntoskrnl/lpc/complete.c Sun Jan 21 20:21:42 2007
@@ -145,7 +145,7 @@
Message->Request.ClientId = ReplyMessage->ClientId;
Message->Request.MessageId = ReplyMessage->MessageId;
Message->Request.ClientViewSize = 0;
- RtlMoveMemory(ConnectMessage + 1, ReplyMessage + 1, ConnectionInfoLength);
+ RtlCopyMemory(ConnectMessage + 1, ReplyMessage + 1, ConnectionInfoLength);
/* At this point, if the caller refused the connection, go to cleanup */
if (!AcceptConnection) goto Cleanup;
@@ -213,6 +213,10 @@
/* Set the view base */
ConnectMessage->ClientView.ViewRemoteBase = ServerPort->
ClientSectionBase;
+
+ /* Save and reference the mapping process */
+ ServerPort->MappingProcess = PsGetCurrentProcess();
+ ObReferenceObject(ServerPort->MappingProcess);
}
else
{
@@ -351,10 +355,10 @@
/* Make sure it has a reply message */
if (!Thread->LpcReplyMessage)
{
- /* It doesn't, fail */
+ /* It doesn't, quit */
KeReleaseGuardedMutex(&LpcpLock);
ObDereferenceObject(Port);
- return STATUS_PORT_DISCONNECTED;
+ return STATUS_SUCCESS;
}
/* Clear the client thread and wake it up */
Modified: trunk/reactos/ntoskrnl/lpc/connect.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/lpc/connect.c?rev…
==============================================================================
--- trunk/reactos/ntoskrnl/lpc/connect.c (original)
+++ trunk/reactos/ntoskrnl/lpc/connect.c Sun Jan 21 20:21:42 2007
@@ -21,6 +21,7 @@
IN PETHREAD CurrentThread)
{
PVOID SectionToMap;
+ PLPCP_MESSAGE ReplyMessage;
/* Acquire the LPC lock */
KeAcquireGuardedMutex(&LpcpLock);
@@ -34,10 +35,19 @@
}
/* Check if there's a reply message */
- if (CurrentThread->LpcReplyMessage)
+ ReplyMessage = CurrentThread->LpcReplyMessage;
+ if (ReplyMessage)
{
/* Get the message */
- *Message = CurrentThread->LpcReplyMessage;
+ *Message = ReplyMessage;
+
+ /* Check if it's got messages */
+ if (!IsListEmpty(&ReplyMessage->Entry))
+ {
+ /* Clear the list */
+ RemoveEntryList(&ReplyMessage->Entry);
+ InitializeListHead(&ReplyMessage->Entry);
+ }
/* Clear message data */
CurrentThread->LpcReceivedMessageId = 0;
@@ -124,7 +134,7 @@
Status = ObReferenceObjectByName(PortName,
0,
NULL,
- PORT_ALL_ACCESS,
+ PORT_CONNECT,
LpcPortObjectType,
PreviousMode,
NULL,
@@ -286,6 +296,10 @@
/* Update the base */
ClientView->ViewBase = Port->ClientSectionBase;
+
+ /* Reference and remember the process */
+ ClientPort->MappingProcess = PsGetCurrentProcess();
+ ObReferenceObject(ClientPort->MappingProcess);
}
else
{
@@ -321,7 +335,7 @@
Message->Request.ClientViewSize = ClientView->ViewSize;
/* Copy the client view and clear the server view */
- RtlMoveMemory(&ConnectMessage->ClientView,
+ RtlCopyMemory(&ConnectMessage->ClientView,
ClientView,
sizeof(PORT_VIEW));
RtlZeroMemory(&ConnectMessage->ServerView, sizeof(REMOTE_PORT_VIEW));
@@ -348,7 +362,7 @@
if (ConnectionInformation)
{
/* Copy it in */
- RtlMoveMemory(ConnectMessage + 1,
+ RtlCopyMemory(ConnectMessage + 1,
ConnectionInformation,
ConnectionInfoLength);
}
@@ -360,51 +374,63 @@
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;
+ }
+ else
+ {
+ /* 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;
+
+ /* Enter a critical region */
+ KeEnterCriticalRegion();
+ }
+
+ /* Add another reference to the port */
+ ObReferenceObject(Port);
/* 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;
+
+ /* Check for success */
+ if (NT_SUCCESS(Status))
+ {
+ 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 and leave the critical region */
+ LpcpCompleteWait(Port->MsgQueue.Semaphore);
+ KeLeaveCriticalRegion();
+
+ /* Now wait for a reply */
+ LpcpConnectWait(&Thread->LpcReplySemaphore, PreviousMode);
+ }
+
+ /* Check for failure */
+ if (!NT_SUCCESS(Status)) goto Cleanup;
/* Free the connection message */
SectionToMap = LpcpFreeConMsg(&Message, &ConnectMessage, Thread);
@@ -432,7 +458,7 @@
}
/* Return the connection information */
- RtlMoveMemory(ConnectionInformation,
+ RtlCopyMemory(ConnectionInformation,
ConnectMessage + 1,
ConnectionInfoLength );
}
@@ -466,7 +492,7 @@
if (ClientView)
{
/* Copy it back */
- RtlMoveMemory(ClientView,
+ RtlCopyMemory(ClientView,
&ConnectMessage->ClientView,
sizeof(PORT_VIEW));
}
@@ -475,7 +501,7 @@
if (ServerView)
{
/* Copy it back */
- RtlMoveMemory(ServerView,
+ RtlCopyMemory(ServerView,
&ConnectMessage->ServerView,
sizeof(REMOTE_PORT_VIEW));
}
@@ -486,8 +512,12 @@
/* No connection port, we failed */
if (SectionToMap) ObDereferenceObject(SectionToMap);
+ /* Acquire the lock */
+ KeAcquireGuardedMutex(&LpcpLock);
+
/* Check if it's because the name got deleted */
- if (Port->Flags & LPCP_NAME_DELETED)
+ if (!(ClientPort->ConnectionPort) ||
+ (Port->Flags & LPCP_NAME_DELETED))
{
/* Set the correct status */
Status = STATUS_OBJECT_NAME_NOT_FOUND;
@@ -498,19 +528,27 @@
Status = STATUS_PORT_CONNECTION_REFUSED;
}
+ /* Release the lock */
+ KeReleaseGuardedMutex(&LpcpLock);
+
/* 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;
+ LpcpFreeToPortZone(Message, 0);
+ }
+ else
+ {
+ /* No reply message, fail */
+ if (SectionToMap) ObDereferenceObject(SectionToMap);
+ ObDereferenceObject(ClientPort);
+ Status = STATUS_PORT_CONNECTION_REFUSED;
+ }
+
+ /* Return status */
+ ObDereferenceObject(Port);
+ return Status;
Cleanup:
/* We failed, free the message */
@@ -521,20 +559,21 @@
{
/* Wait on it */
KeWaitForSingleObject(&Thread->LpcReplySemaphore,
+ WrExecutive,
KernelMode,
- Executive,
FALSE,
NULL);
}
/* Check if we had a message and free it */
- if (Message) LpcpFreeToPortZone(Message, FALSE);
+ if (Message) LpcpFreeToPortZone(Message, 0);
/* Dereference other objects */
if (SectionToMap) ObDereferenceObject(SectionToMap);
ObDereferenceObject(ClientPort);
/* Return status */
+ ObDereferenceObject(Port);
return Status;
}
Modified: trunk/reactos/ntoskrnl/lpc/create.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/lpc/create.c?rev=…
==============================================================================
--- trunk/reactos/ntoskrnl/lpc/create.c (original)
+++ trunk/reactos/ntoskrnl/lpc/create.c Sun Jan 21 20:21:42 2007
@@ -19,6 +19,7 @@
LpcpInitializePortQueue(IN PLPCP_PORT_OBJECT Port)
{
PLPCP_NONPAGED_PORT_QUEUE MessageQueue;
+ PAGED_CODE();
/* Allocate the queue */
MessageQueue = ExAllocatePoolWithTag(NonPagedPool,
@@ -48,6 +49,7 @@
KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
NTSTATUS Status;
PLPCP_PORT_OBJECT Port;
+ PAGED_CODE();
LPCTRACE(LPC_CREATE_DEBUG, "Name: %wZ\n",
ObjectAttributes->ObjectName);
/* Create the Object */
Modified: trunk/reactos/ntoskrnl/lpc/listen.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/lpc/listen.c?rev=…
==============================================================================
--- trunk/reactos/ntoskrnl/lpc/listen.c (original)
+++ trunk/reactos/ntoskrnl/lpc/listen.c Sun Jan 21 20:21:42 2007
@@ -22,30 +22,30 @@
NtListenPort(IN HANDLE PortHandle,
OUT PPORT_MESSAGE ConnectMessage)
{
- NTSTATUS Status;
- PAGED_CODE();
- LPCTRACE(LPC_LISTEN_DEBUG, "Handle: %lx\n", PortHandle);
+ NTSTATUS Status;
+ PAGED_CODE();
+ LPCTRACE(LPC_LISTEN_DEBUG, "Handle: %lx\n", PortHandle);
- /* Wait forever for a connection request. */
- for (;;)
+ /* 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))
{
- /* Do the wait */
- Status = NtReplyWaitReceivePort(PortHandle,
- NULL,
- NULL,
- ConnectMessage);
+ /* Break out */
+ break;
+ }
+ }
- /* Accept only LPC_CONNECTION_REQUEST requests. */
- if ((Status != STATUS_SUCCESS) ||
- (LpcpGetMessageType(ConnectMessage) == LPC_CONNECTION_REQUEST))
- {
- /* Break out */
- break;
- }
- }
-
- /* Return status */
- return Status;
+ /* Return status */
+ return Status;
}
Modified: trunk/reactos/ntoskrnl/lpc/port.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/lpc/port.c?rev=25…
==============================================================================
--- trunk/reactos/ntoskrnl/lpc/port.c (original)
+++ trunk/reactos/ntoskrnl/lpc/port.c Sun Jan 21 20:21:42 2007
@@ -18,7 +18,7 @@
ULONG LpcpMaxMessageSize;
PAGED_LOOKASIDE_LIST LpcpMessagesLookaside;
KGUARDED_MUTEX LpcpLock;
-ULONG LpcpTraceLevel = 0;
+ULONG LpcpTraceLevel = LPC_CLOSE_DEBUG;
ULONG LpcpNextMessageId = 1, LpcpNextCallbackId = 1;
static GENERIC_MAPPING LpcpPortMapping =
@@ -54,7 +54,6 @@
ObjectTypeInitializer.CloseProcedure = LpcpClosePort;
ObjectTypeInitializer.DeleteProcedure = LpcpDeletePort;
ObjectTypeInitializer.ValidAccessMask = PORT_ALL_ACCESS;
- ObjectTypeInitializer.MaintainTypeList = TRUE;
ObCreateObjectType(&Name,
&ObjectTypeInitializer,
NULL,
Modified: trunk/reactos/ntoskrnl/lpc/reply.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/lpc/reply.c?rev=2…
==============================================================================
--- trunk/reactos/ntoskrnl/lpc/reply.c (original)
+++ trunk/reactos/ntoskrnl/lpc/reply.c Sun Jan 21 20:21:42 2007
@@ -18,7 +18,8 @@
NTAPI
LpcpFreeDataInfoMessage(IN PLPCP_PORT_OBJECT Port,
IN ULONG MessageId,
- IN ULONG CallbackId)
+ IN ULONG CallbackId,
+ IN CLIENT_ID ClientId)
{
PLPCP_MESSAGE Message;
PLIST_ENTRY ListHead, NextEntry;
@@ -28,6 +29,7 @@
{
/* Use it */
Port = Port->ConnectionPort;
+ if (!Port) return;
}
/* Loop the list */
@@ -40,12 +42,13 @@
/* Make sure it matches */
if ((Message->Request.MessageId == MessageId) &&
- (Message->Request.CallbackId == CallbackId))
+ (Message->Request.ClientId.UniqueThread == ClientId.UniqueThread)
&&
+ (Message->Request.ClientId.UniqueProcess == ClientId.UniqueProcess))
{
/* Unlink and free it */
RemoveEntryList(&Message->Entry);
InitializeListHead(&Message->Entry);
- LpcpFreeToPortZone(Message, TRUE);
+ LpcpFreeToPortZone(Message, 1);
break;
}
@@ -58,25 +61,31 @@
NTAPI
LpcpSaveDataInfoMessage(IN PLPCP_PORT_OBJECT Port,
IN PLPCP_MESSAGE Message,
- IN ULONG LockFlags)
+ IN ULONG LockHeld)
{
PAGED_CODE();
/* Acquire the lock */
- KeAcquireGuardedMutex(&LpcpLock);
+ if (!LockHeld) 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;
+ if (!Port)
+ {
+ /* Release the lock and return */
+ if (!LockHeld) KeReleaseGuardedMutex(&LpcpLock);
+ return;
+ }
}
/* Link the message */
InsertTailList(&Port->LpcDataInfoChainHead, &Message->Entry);
/* Release the lock */
- KeReleaseGuardedMutex(&LpcpLock);
+ if (!LockHeld) KeReleaseGuardedMutex(&LpcpLock);
}
VOID
@@ -119,7 +128,7 @@
Destination->ClientViewSize = Origin->ClientViewSize;
/* Copy the Message Data */
- RtlMoveMemory(Destination + 1,
+ RtlCopyMemory(Destination + 1,
Data,
((Destination->u1.Length & 0xFFFF) + 3) &~3);
}
@@ -149,7 +158,7 @@
OUT PPORT_MESSAGE ReceiveMessage,
IN PLARGE_INTEGER Timeout OPTIONAL)
{
- PLPCP_PORT_OBJECT Port, ReceivePort;
+ PLPCP_PORT_OBJECT Port, ReceivePort, ConnectionPort = NULL;
KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(), WaitMode = PreviousMode;
NTSTATUS Status;
PLPCP_MESSAGE Message;
@@ -207,8 +216,32 @@
/* 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;
+ /* Check if this is the connection port */
+ if (Port->ConnectionPort == Port)
+ {
+ /* Use this port */
+ ConnectionPort = ReceivePort = Port;
+ ObReferenceObject(ConnectionPort);
+ }
+ else
+ {
+ /* Acquire the lock */
+ KeAcquireGuardedMutex(&LpcpLock);
+
+ /* Get the port */
+ ConnectionPort = ReceivePort = Port->ConnectionPort;
+ if (!ConnectionPort)
+ {
+ /* Fail */
+ KeReleaseGuardedMutex(&LpcpLock);
+ ObDereferenceObject(Port);
+ return STATUS_PORT_DISCONNECTED;
+ }
+
+ /* Release lock and reference */
+ ObReferenceObject(Port);
+ KeReleaseGuardedMutex(&LpcpLock);
+ }
}
else
{
@@ -227,6 +260,7 @@
{
/* No thread found, fail */
ObDereferenceObject(Port);
+ if (ConnectionPort) ObDereferenceObject(ConnectionPort);
return Status;
}
@@ -235,6 +269,7 @@
if (!Message)
{
/* Fail if we couldn't allocate a message */
+ if (ConnectionPort) ObDereferenceObject(ConnectionPort);
ObDereferenceObject(WakeupThread);
ObDereferenceObject(Port);
return STATUS_NO_MEMORY;
@@ -244,11 +279,16 @@
KeAcquireGuardedMutex(&LpcpLock);
/* Make sure this is the reply the thread is waiting for */
- if (WakeupThread->LpcReplyMessageId != ReplyMessage->MessageId)
+ if ((WakeupThread->LpcReplyMessageId != ReplyMessage->MessageId))// ||
+#if 0
+ ((WakeupThread->LpcReplyMessage) &&
+ (LpcpGetMessageType(&((PLPCP_MESSAGE)WakeupThread->
+ LpcReplyMessage)->Request) != LPC_REQUEST)))
+#endif
{
/* It isn't, fail */
- LpcpFreeToPortZone(Message, TRUE);
- KeReleaseGuardedMutex(&LpcpLock);
+ LpcpFreeToPortZone(Message, 3);
+ if (ConnectionPort) ObDereferenceObject(ConnectionPort);
ObDereferenceObject(WakeupThread);
ObDereferenceObject(Port);
return STATUS_REPLY_MESSAGE_MISMATCH;
@@ -261,36 +301,37 @@
LPC_REPLY,
NULL);
+ /* 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;
+ }
+
/* 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;
- }
+ ReplyMessage->CallbackId,
+ ReplyMessage->ClientId);
/* Release the lock and release the LPC semaphore to wake up waiters */
KeReleaseGuardedMutex(&LpcpLock);
@@ -319,6 +360,7 @@
/* Release the lock and fail */
KeReleaseGuardedMutex(&LpcpLock);
+ if (ConnectionPort) ObDereferenceObject(ConnectionPort);
ObDereferenceObject(Port);
return STATUS_UNSUCCESSFUL;
}
@@ -346,9 +388,6 @@
/* 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)
@@ -374,7 +413,7 @@
ReceiveMessage->u1.s1.TotalLength = sizeof(LPCP_MESSAGE) +
ConnectionInfoLength;
ReceiveMessage->u1.s1.DataLength = ConnectionInfoLength;
- RtlMoveMemory(ReceiveMessage + 1,
+ RtlCopyMemory(ReceiveMessage + 1,
ConnectMessage + 1,
ConnectionInfoLength);
@@ -413,8 +452,17 @@
ASSERT(FALSE);
}
- /* If we have a message pointer here, free it */
- if (Message) LpcpFreeToPortZone(Message, FALSE);
+ /* Check if we have a message pointer here */
+ if (Message)
+ {
+ /* Free it and release the lock */
+ LpcpFreeToPortZone(Message, 3);
+ }
+ else
+ {
+ /* Just release the lock */
+ KeReleaseGuardedMutex(&LpcpLock);
+ }
Cleanup:
/* All done, dereference the port and return the status */
@@ -422,6 +470,7 @@
"Port: %p. Status: %p\n",
Port,
Status);
+ if (ConnectionPort) ObDereferenceObject(ConnectionPort);
ObDereferenceObject(Port);
return Status;
}
Modified: trunk/reactos/ntoskrnl/lpc/send.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/lpc/send.c?rev=25…
==============================================================================
--- trunk/reactos/ntoskrnl/lpc/send.c (original)
+++ trunk/reactos/ntoskrnl/lpc/send.c Sun Jan 21 20:21:42 2007
@@ -22,7 +22,7 @@
LpcRequestPort(IN PVOID PortObject,
IN PPORT_MESSAGE LpcMessage)
{
- PLPCP_PORT_OBJECT Port = (PLPCP_PORT_OBJECT)PortObject, QueuePort;
+ PLPCP_PORT_OBJECT Port = PortObject, QueuePort, ConnectionPort = NULL;
ULONG MessageType;
PLPCP_MESSAGE Message;
KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
@@ -42,7 +42,7 @@
return STATUS_INVALID_PARAMETER;
}
- /* Mark this as a kernel-mode message only if we really came from there */
+ /* Mark this as a kernel-mode message only if we really came from it */
if ((PreviousMode == KernelMode) &&
(LpcMessage->u2.s2.Type & LPC_KERNELMODE_MESSAGE))
{
@@ -72,6 +72,7 @@
if (!Message) return STATUS_NO_MEMORY;
/* Clear the context */
+ Message->RepliedToThread = NULL;
Message->PortContext = NULL;
/* Copy the message */
@@ -96,13 +97,28 @@
{
/* Then copy the context */
Message->PortContext = QueuePort->PortContext;
- QueuePort = Port->ConnectionPort;
+ ConnectionPort = QueuePort = Port->ConnectionPort;
+ if (!ConnectionPort)
+ {
+ /* Fail */
+ LpcpFreeToPortZone(Message, 3);
+ return STATUS_PORT_DISCONNECTED;
+ }
}
else if ((Port->Flags & LPCP_PORT_TYPE_MASK) !=
LPCP_COMMUNICATION_PORT)
{
/* Any other kind of port, use the connection port */
- QueuePort = Port->ConnectionPort;
- }
+ ConnectionPort = QueuePort = Port->ConnectionPort;
+ if (!ConnectionPort)
+ {
+ /* Fail */
+ LpcpFreeToPortZone(Message, 3);
+ return STATUS_PORT_DISCONNECTED;
+ }
+ }
+
+ /* If we have a connection port, reference it */
+ if (ConnectionPort) ObReferenceObject(ConnectionPort);
}
}
else
@@ -126,6 +142,7 @@
InsertTailList(&QueuePort->MsgQueue.ReceiveHead, &Message->Entry);
/* Release the lock and release the semaphore */
+ KeEnterCriticalRegion();
KeReleaseGuardedMutex(&LpcpLock);
LpcpCompleteWait(QueuePort->MsgQueue.Semaphore);
@@ -137,13 +154,15 @@
}
/* We're done */
+ KeLeaveCriticalRegion();
LPCTRACE(LPC_SEND_DEBUG, "Port: %p. Message: %p\n", QueuePort,
Message);
+ if (ConnectionPort) ObDereferenceObject(ConnectionPort);
return STATUS_SUCCESS;
}
/* If we got here, then free the message and fail */
- LpcpFreeToPortZone(Message, TRUE);
- KeReleaseGuardedMutex(&LpcpLock);
+ LpcpFreeToPortZone(Message, 3);
+ if (ConnectionPort) ObDereferenceObject(ConnectionPort);
return STATUS_PORT_DISCONNECTED;
}
@@ -181,7 +200,7 @@
IN PPORT_MESSAGE LpcRequest,
IN OUT PPORT_MESSAGE LpcReply)
{
- PLPCP_PORT_OBJECT Port, QueuePort, ReplyPort;
+ PLPCP_PORT_OBJECT Port, QueuePort, ReplyPort, ConnectionPort = NULL;
KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
NTSTATUS Status;
PLPCP_MESSAGE Message;
@@ -286,8 +305,7 @@
if (!QueuePort)
{
/* We have no connected port, fail */
- LpcpFreeToPortZone(Message, TRUE);
- KeReleaseGuardedMutex(&LpcpLock);
+ LpcpFreeToPortZone(Message, 3);
ObDereferenceObject(Port);
return STATUS_PORT_DISCONNECTED;
}
@@ -299,15 +317,32 @@
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;
+ Message->PortContext = QueuePort->PortContext;
+ ConnectionPort = QueuePort = Port->ConnectionPort;
+ if (!ConnectionPort)
+ {
+ /* Fail */
+ LpcpFreeToPortZone(Message, 3);
+ ObDereferenceObject(Port);
+ return STATUS_PORT_DISCONNECTED;
+ }
}
else if ((Port->Flags & LPCP_PORT_TYPE_MASK) !=
LPCP_COMMUNICATION_PORT)
{
/* Use the connection port for anything but communication ports */
- QueuePort = Port->ConnectionPort;
- }
+ ConnectionPort = QueuePort = Port->ConnectionPort;
+ if (!ConnectionPort)
+ {
+ /* Fail */
+ LpcpFreeToPortZone(Message, 3);
+ ObDereferenceObject(Port);
+ return STATUS_PORT_DISCONNECTED;
+ }
+ }
+
+ /* Reference the connection port if it exists */
+ if (ConnectionPort) ObReferenceObject(ConnectionPort);
}
else
{
@@ -317,6 +352,7 @@
/* No reply thread */
Message->RepliedToThread = NULL;
+ Message->SenderPort = Port;
/* Generate the Message ID and set it */
Message->Request.MessageId = LpcpNextMessageId++;
@@ -330,8 +366,10 @@
/* Insert the message in our chain */
InsertTailList(&QueuePort->MsgQueue.ReceiveHead, &Message->Entry);
InsertTailList(&ReplyPort->LpcReplyChainHead,
&Thread->LpcReplyChain);
+ Thread->LpcWaitingOnPort = Port;
/* Release the lock and get the semaphore we'll use later */
+ KeEnterCriticalRegion();
KeReleaseGuardedMutex(&LpcpLock);
Semaphore = QueuePort->MsgQueue.Semaphore;
@@ -345,6 +383,7 @@
/* Now release the semaphore */
LpcpCompleteWait(Semaphore);
+ KeLeaveCriticalRegion();
/* And let's wait for the reply */
LpcpReplyWait(&Thread->LpcReplySemaphore, PreviousMode);
@@ -396,7 +435,7 @@
else
{
/* Otherwise, just free it */
- LpcpFreeToPortZone(Message, FALSE);
+ LpcpFreeToPortZone(Message, 0);
}
}
else
@@ -407,10 +446,8 @@
}
else
{
- /* The wait failed, free the message while holding the lock */
- KeAcquireGuardedMutex(&LpcpLock);
- LpcpFreeToPortZone(Message, TRUE);
- KeReleaseGuardedMutex(&LpcpLock);
+ /* The wait failed, free the message */
+ if (Message) LpcpFreeToPortZone(Message, 0);
}
/* All done */
@@ -419,6 +456,7 @@
Port,
Status);
ObDereferenceObject(Port);
+ if (ConnectionPort) ObDereferenceObject(ConnectionPort);
return Status;
}