- Fix HANDLE_TABLE definition.
authorAlex Ionescu <aionescu@gmail.com>
Mon, 22 Jan 2007 08:07:24 +0000 (08:07 +0000)
committerAlex Ionescu <aionescu@gmail.com>
Mon, 22 Jan 2007 08:07:24 +0000 (08:07 +0000)
- 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.

svn path=/trunk/; revision=25585

reactos/include/ndk/extypes.h
reactos/ntoskrnl/include/internal/lpc.h
reactos/ntoskrnl/include/internal/lpc_x.h
reactos/ntoskrnl/lpc/close.c
reactos/ntoskrnl/lpc/complete.c
reactos/ntoskrnl/lpc/connect.c
reactos/ntoskrnl/lpc/reply.c
reactos/ntoskrnl/lpc/send.c

index 47439cd..01cb60d 100644 (file)
@@ -592,14 +592,6 @@ typedef struct _HANDLE_TABLE_ENTRY
     };
 } 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 @@ typedef struct _HANDLE_TABLE
     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
index 2eba448..6dc86d6 100644 (file)
 #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
 //
index a1cc008..6e8acf5 100644 (file)
@@ -120,3 +120,47 @@ LpcpAllocateFromPortZone(VOID)
     KeReleaseGuardedMutex(&LpcpLock);\r
     return Message;\r
 }\r
+\r
+//\r
+// Get the LPC Message associated to the Thread\r
+//\r
+PLPCP_MESSAGE\r
+FORCEINLINE\r
+LpcpGetMessageFromThread(IN PETHREAD Thread)\r
+{\r
+    /* Check if the port flag is set */\r
+    if (((ULONG_PTR)Thread->LpcReplyMessage) & LPCP_THREAD_FLAG_IS_PORT)\r
+    {\r
+        /* The pointer is actually a port, not a message, so return NULL */\r
+        return NULL;\r
+    }\r
+\r
+    /* Otherwise, this is a message. Return the pointer */\r
+    return (PVOID)((ULONG_PTR)Thread->LpcReplyMessage & ~LPCP_THREAD_FLAGS);\r
+}\r
+\r
+PLPCP_PORT_OBJECT\r
+FORCEINLINE\r
+LpcpGetPortFromThread(IN PETHREAD Thread)\r
+{\r
+    /* Check if the port flag is set */\r
+    if (((ULONG_PTR)Thread->LpcReplyMessage) & LPCP_THREAD_FLAG_IS_PORT)\r
+    {\r
+        /* The pointer is actually a port, return it */\r
+        return (PVOID)((ULONG_PTR)Thread->LpcWaitingOnPort &\r
+                       ~LPCP_THREAD_FLAGS);\r
+    }\r
+\r
+    /* Otherwise, this is a message. There is nothing to return */\r
+    return NULL;\r
+}\r
+\r
+VOID\r
+FORCEINLINE\r
+LpcpSetPortToThread(IN PETHREAD Thread,\r
+                    IN PLPCP_PORT_OBJECT Port)\r
+{\r
+    /* Set the port object */\r
+    Thread->LpcWaitingOnPort = (PVOID)(((ULONG_PTR)Port) |\r
+                                       LPCP_THREAD_FLAG_IS_PORT);\r
+}\r
index 95d4071..d142d0f 100644 (file)
@@ -36,7 +36,7 @@ LpcExitThread(IN PETHREAD Thread)
     Thread->LpcReplyMessageId = 0;
 
     /* Check if there's a reply message */
-    Message = Thread->LpcReplyMessage;
+    Message = LpcpGetMessageFromThread(Thread);
     if (Message)
     {
         /* FIXME: TODO */
@@ -57,7 +57,7 @@ LpcpFreeToPortZone(IN PLPCP_MESSAGE Message,
     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 @@ LpcpDestroyPortQueue(IN PLPCP_PORT_OBJECT Port,
     {
         /* Disconnect it */
         Port->ConnectedPort->ConnectedPort = NULL;
-        if (Port->ConnectedPort->ConnectionPort)
+        ConnectionPort = Port->ConnectedPort->ConnectionPort;
+        if (ConnectionPort)
         {
-            /* Save and clear connection port */
-            ConnectionPort = Port->ConnectedPort->ConnectionPort;
+            /* Clear connection port */
             Port->ConnectedPort->ConnectionPort = NULL;
         }
     }
@@ -162,7 +162,7 @@ LpcpDestroyPortQueue(IN PLPCP_PORT_OBJECT Port,
         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 @@ LpcpDestroyPortQueue(IN PLPCP_PORT_OBJECT Port,
 
     /* 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 @@ LpcpDeletePort(IN PVOID ObjectBody)
         /* Send it */
         for (;;)
         {
-            /* FIXME: HACK OF D00m */
-            break;
-
             /* Send the message */
             if (LpcRequestPort(Port,
                                &ClientDiedMsg.h) != STATUS_NO_MEMORY) break;
index 33c6886..6acbd2f 100644 (file)
@@ -88,7 +88,7 @@ NtAcceptConnectPort(OUT PHANDLE PortHandle,
     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 @@ NtAcceptConnectPort(OUT PHANDLE PortHandle,
     }
 
     /* 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 @@ NtCompleteConnectPort(IN HANDLE PortHandle)
     Thread = Port->ClientThread;
 
     /* Make sure it has a reply message */
-    if (!Thread->LpcReplyMessage)
+    if (!LpcpGetMessageFromThread(Thread))
     {
         /* It doesn't, quit */
         KeReleaseGuardedMutex(&LpcpLock);
index da0dcde..6031ece 100644 (file)
@@ -35,7 +35,7 @@ LpcpFreeConMsg(IN OUT PLPCP_MESSAGE *Message,
     }
 
     /* Check if there's a reply message */
-    ReplyMessage = CurrentThread->LpcReplyMessage;
+    ReplyMessage = LpcpGetMessageFromThread(CurrentThread);
     if (ReplyMessage)
     {
         /* Get the message */
@@ -54,7 +54,7 @@ LpcpFreeConMsg(IN OUT PLPCP_MESSAGE *Message,
         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;
     }
index ac421fb..ae69951 100644 (file)
@@ -279,12 +279,10 @@ NtReplyWaitReceivePortEx(IN HANDLE PortHandle,
         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);
index 525267c..952f4ae 100644 (file)
@@ -155,8 +155,8 @@ LpcRequestPort(IN PVOID PortObject,
 
         /* We're done */
         KeLeaveCriticalRegion();
-        LPCTRACE(LPC_SEND_DEBUG, "Port: %p. Message: %p\n", QueuePort, Message);
         if (ConnectionPort) ObDereferenceObject(ConnectionPort);
+        LPCTRACE(LPC_SEND_DEBUG, "Port: %p. Message: %p\n", QueuePort, Message);
         return STATUS_SUCCESS;
     }
 
@@ -366,7 +366,7 @@ NtRequestWaitReplyPort(IN HANDLE PortHandle,
         /* 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 @@ NtRequestWaitReplyPort(IN HANDLE PortHandle,
     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;