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;