Author: ion
Date: Mon Jan 22 11:07:24 2007
New Revision: 25585
URL:
http://svn.reactos.org/svn/reactos?rev=25585&view=rev
Log:
- Fix HANDLE_TABLE definition.
- Fix LPC bugcheck during 2nd stage setup and/or bootup (double-free):
- LpcReplyMessage and LpcWaitingOnPort are a union inside ETHREAD, and they can actually
be both accessed in the same time! (Unlike other unions which are self-exclusive).
Therefore, we need a way to:
1) Mark a message vs a port.
2) Retrieve the correct object.
This has now been implemented with some helper inline functions.
Modified:
trunk/reactos/include/ndk/extypes.h
trunk/reactos/ntoskrnl/include/internal/lpc.h
trunk/reactos/ntoskrnl/include/internal/lpc_x.h
trunk/reactos/ntoskrnl/lpc/close.c
trunk/reactos/ntoskrnl/lpc/complete.c
trunk/reactos/ntoskrnl/lpc/connect.c
trunk/reactos/ntoskrnl/lpc/reply.c
trunk/reactos/ntoskrnl/lpc/send.c
Modified: trunk/reactos/include/ndk/extypes.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/include/ndk/extypes.h?rev=…
==============================================================================
--- trunk/reactos/include/ndk/extypes.h (original)
+++ trunk/reactos/include/ndk/extypes.h Mon Jan 22 11:07:24 2007
@@ -592,14 +592,6 @@
};
} HANDLE_TABLE_ENTRY, *PHANDLE_TABLE_ENTRY;
-//
-// FIXME
-//
-#ifdef _REACTOS_
-#undef NTDDI_VERSION
-#define NTDDI_VERSION NTDDI_WIN2K
-#endif
-
typedef struct _HANDLE_TABLE
{
#if (NTDDI_VERSION >= NTDDI_WINXP)
@@ -610,7 +602,7 @@
PEPROCESS QuotaProcess;
PVOID UniqueProcessId;
#if (NTDDI_VERSION >= NTDDI_WINXP)
- EX_PUSH_LOCK HandleLock;
+ EX_PUSH_LOCK HandleTableLock[4];
LIST_ENTRY HandleTableList;
EX_PUSH_LOCK HandleContentionEvent;
#else
Modified: trunk/reactos/ntoskrnl/include/internal/lpc.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/lpc.h (original)
+++ trunk/reactos/ntoskrnl/include/internal/lpc.h Mon Jan 22 11:07:24 2007
@@ -46,6 +46,14 @@
}
#endif
#endif
+
+//
+// LPC Port/Message Flags
+//
+#define LPCP_THREAD_FLAG_IS_PORT 1
+#define LPCP_THREAD_FLAG_NO_IMPERSONATION 2
+#define LPCP_THREAD_FLAGS (LPCP_THREAD_FLAG_IS_PORT |
\
+
LPCP_THREAD_FLAG_NO_IMPERSONATION)
//
// Internal Port Management
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 Mon Jan 22 11:07:24 2007
@@ -120,3 +120,47 @@
KeReleaseGuardedMutex(&LpcpLock);
return Message;
}
+
+//
+// Get the LPC Message associated to the Thread
+//
+PLPCP_MESSAGE
+FORCEINLINE
+LpcpGetMessageFromThread(IN PETHREAD Thread)
+{
+ /* Check if the port flag is set */
+ if (((ULONG_PTR)Thread->LpcReplyMessage) & LPCP_THREAD_FLAG_IS_PORT)
+ {
+ /* The pointer is actually a port, not a message, so return NULL */
+ return NULL;
+ }
+
+ /* Otherwise, this is a message. Return the pointer */
+ return (PVOID)((ULONG_PTR)Thread->LpcReplyMessage & ~LPCP_THREAD_FLAGS);
+}
+
+PLPCP_PORT_OBJECT
+FORCEINLINE
+LpcpGetPortFromThread(IN PETHREAD Thread)
+{
+ /* Check if the port flag is set */
+ if (((ULONG_PTR)Thread->LpcReplyMessage) & LPCP_THREAD_FLAG_IS_PORT)
+ {
+ /* The pointer is actually a port, return it */
+ return (PVOID)((ULONG_PTR)Thread->LpcWaitingOnPort &
+ ~LPCP_THREAD_FLAGS);
+ }
+
+ /* Otherwise, this is a message. There is nothing to return */
+ return NULL;
+}
+
+VOID
+FORCEINLINE
+LpcpSetPortToThread(IN PETHREAD Thread,
+ IN PLPCP_PORT_OBJECT Port)
+{
+ /* Set the port object */
+ Thread->LpcWaitingOnPort = (PVOID)(((ULONG_PTR)Port) |
+ LPCP_THREAD_FLAG_IS_PORT);
+}
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 Mon Jan 22 11:07:24 2007
@@ -36,7 +36,7 @@
Thread->LpcReplyMessageId = 0;
/* Check if there's a reply message */
- Message = Thread->LpcReplyMessage;
+ Message = LpcpGetMessageFromThread(Thread);
if (Message)
{
/* FIXME: TODO */
@@ -57,7 +57,7 @@
PETHREAD Thread = NULL;
BOOLEAN LockHeld = Flags & 1, ReleaseLock = Flags & 2;
PAGED_CODE();
- DPRINT1("Message: %p. Flags: %lx\n", Message, Flags);
+ LPCTRACE(LPC_CLOSE_DEBUG, "Message: %p. Flags: %lx\n", Message, Flags);
/* Acquire the lock if not already */
if (!LockHeld) KeAcquireGuardedMutex(&LpcpLock);
@@ -125,10 +125,10 @@
{
/* Disconnect it */
Port->ConnectedPort->ConnectedPort = NULL;
- if (Port->ConnectedPort->ConnectionPort)
- {
- /* Save and clear connection port */
- ConnectionPort = Port->ConnectedPort->ConnectionPort;
+ ConnectionPort = Port->ConnectedPort->ConnectionPort;
+ if (ConnectionPort)
+ {
+ /* Clear connection port */
Port->ConnectedPort->ConnectionPort = NULL;
}
}
@@ -162,7 +162,7 @@
if (!KeReadStateSemaphore(&Thread->LpcReplySemaphore))
{
/* Get the message */
- Message = Thread->LpcReplyMessage;
+ Message = LpcpGetMessageFromThread(Thread);
if (Message)
{
/* Check if it's a connection request */
@@ -198,7 +198,7 @@
/* Loop queued messages */
while ((Port->MsgQueue.ReceiveHead.Flink) &&
- !(IsListEmpty (&Port->MsgQueue.ReceiveHead)))
+ !(IsListEmpty(&Port->MsgQueue.ReceiveHead)))
{
/* Get the message */
Message = CONTAINING_RECORD(Port->MsgQueue.ReceiveHead.Flink,
@@ -342,9 +342,6 @@
/* Send it */
for (;;)
{
- /* FIXME: HACK OF D00m */
- break;
-
/* Send the message */
if (LpcRequestPort(Port,
&ClientDiedMsg.h) != STATUS_NO_MEMORY) break;
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 Mon Jan 22 11:07:24 2007
@@ -88,7 +88,7 @@
KeAcquireGuardedMutex(&LpcpLock);
/* Make sure that the client wants a reply, and this is the right one */
- if (!(ClientThread->LpcReplyMessage) ||
+ if (!(LpcpGetMessageFromThread(ClientThread)) ||
!(ReplyMessage->MessageId) ||
(ClientThread->LpcReplyMessageId != ReplyMessage->MessageId))
{
@@ -100,7 +100,7 @@
}
/* Now get the message and connection message */
- Message = ClientThread->LpcReplyMessage;
+ Message = LpcpGetMessageFromThread(ClientThread);
ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(Message + 1);
/* Get the client and connection port as well */
@@ -353,7 +353,7 @@
Thread = Port->ClientThread;
/* Make sure it has a reply message */
- if (!Thread->LpcReplyMessage)
+ if (!LpcpGetMessageFromThread(Thread))
{
/* It doesn't, quit */
KeReleaseGuardedMutex(&LpcpLock);
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 Mon Jan 22 11:07:24 2007
@@ -35,7 +35,7 @@
}
/* Check if there's a reply message */
- ReplyMessage = CurrentThread->LpcReplyMessage;
+ ReplyMessage = LpcpGetMessageFromThread(CurrentThread);
if (ReplyMessage)
{
/* Get the message */
@@ -54,7 +54,7 @@
CurrentThread->LpcReplyMessage = NULL;
/* Get the connection message and clear the section */
- *ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(*Message + 1);
+ *ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(ReplyMessage + 1);
SectionToMap = (*ConnectMessage)->SectionToMap;
(*ConnectMessage)->SectionToMap = 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 Mon Jan 22 11:07:24 2007
@@ -279,12 +279,10 @@
KeAcquireGuardedMutex(&LpcpLock);
/* Make sure this is the reply the thread is waiting for */
- if ((WakeupThread->LpcReplyMessageId != ReplyMessage->MessageId))// ||
-#if 0
- ((WakeupThread->LpcReplyMessage) &&
- (LpcpGetMessageType(&((PLPCP_MESSAGE)WakeupThread->
- LpcReplyMessage)->Request) != LPC_REQUEST)))
-#endif
+ if ((WakeupThread->LpcReplyMessageId != ReplyMessage->MessageId) ||
+ ((LpcpGetMessageFromThread(WakeupThread)) &&
+ (LpcpGetMessageType(&LpcpGetMessageFromThread(WakeupThread)->
+ Request) != LPC_REQUEST)))
{
/* It isn't, fail */
LpcpFreeToPortZone(Message, 3);
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 Mon Jan 22 11:07:24 2007
@@ -155,8 +155,8 @@
/* We're done */
KeLeaveCriticalRegion();
+ if (ConnectionPort) ObDereferenceObject(ConnectionPort);
LPCTRACE(LPC_SEND_DEBUG, "Port: %p. Message: %p\n", QueuePort,
Message);
- if (ConnectionPort) ObDereferenceObject(ConnectionPort);
return STATUS_SUCCESS;
}
@@ -366,7 +366,7 @@
/* Insert the message in our chain */
InsertTailList(&QueuePort->MsgQueue.ReceiveHead, &Message->Entry);
InsertTailList(&ReplyPort->LpcReplyChainHead,
&Thread->LpcReplyChain);
- Thread->LpcWaitingOnPort = Port;
+ LpcpSetPortToThread(Thread, Port);
/* Release the lock and get the semaphore we'll use later */
KeEnterCriticalRegion();
@@ -392,7 +392,7 @@
KeAcquireGuardedMutex(&LpcpLock);
/* Get the LPC Message and clear our thread's reply data */
- Message = Thread->LpcReplyMessage;
+ Message = LpcpGetMessageFromThread(Thread);
Thread->LpcReplyMessage = NULL;
Thread->LpcReplyMessageId = 0;