- 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.

svn path=/trunk/; revision=25585
This commit is contained in:
Alex Ionescu 2007-01-22 08:07:24 +00:00
parent a0d7a72c1a
commit d1c966119b
8 changed files with 72 additions and 33 deletions

View file

@ -592,14 +592,6 @@ typedef struct _HANDLE_TABLE_ENTRY
}; };
} HANDLE_TABLE_ENTRY, *PHANDLE_TABLE_ENTRY; } HANDLE_TABLE_ENTRY, *PHANDLE_TABLE_ENTRY;
//
// FIXME
//
#ifdef _REACTOS_
#undef NTDDI_VERSION
#define NTDDI_VERSION NTDDI_WIN2K
#endif
typedef struct _HANDLE_TABLE typedef struct _HANDLE_TABLE
{ {
#if (NTDDI_VERSION >= NTDDI_WINXP) #if (NTDDI_VERSION >= NTDDI_WINXP)
@ -610,7 +602,7 @@ typedef struct _HANDLE_TABLE
PEPROCESS QuotaProcess; PEPROCESS QuotaProcess;
PVOID UniqueProcessId; PVOID UniqueProcessId;
#if (NTDDI_VERSION >= NTDDI_WINXP) #if (NTDDI_VERSION >= NTDDI_WINXP)
EX_PUSH_LOCK HandleLock; EX_PUSH_LOCK HandleTableLock[4];
LIST_ENTRY HandleTableList; LIST_ENTRY HandleTableList;
EX_PUSH_LOCK HandleContentionEvent; EX_PUSH_LOCK HandleContentionEvent;
#else #else

View file

@ -47,6 +47,14 @@
#endif #endif
#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 // Internal Port Management
// //

View file

@ -120,3 +120,47 @@ LpcpAllocateFromPortZone(VOID)
KeReleaseGuardedMutex(&LpcpLock); KeReleaseGuardedMutex(&LpcpLock);
return Message; 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);
}

View file

@ -36,7 +36,7 @@ LpcExitThread(IN PETHREAD Thread)
Thread->LpcReplyMessageId = 0; Thread->LpcReplyMessageId = 0;
/* Check if there's a reply message */ /* Check if there's a reply message */
Message = Thread->LpcReplyMessage; Message = LpcpGetMessageFromThread(Thread);
if (Message) if (Message)
{ {
/* FIXME: TODO */ /* FIXME: TODO */
@ -57,7 +57,7 @@ LpcpFreeToPortZone(IN PLPCP_MESSAGE Message,
PETHREAD Thread = NULL; PETHREAD Thread = NULL;
BOOLEAN LockHeld = Flags & 1, ReleaseLock = Flags & 2; BOOLEAN LockHeld = Flags & 1, ReleaseLock = Flags & 2;
PAGED_CODE(); 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 */ /* Acquire the lock if not already */
if (!LockHeld) KeAcquireGuardedMutex(&LpcpLock); if (!LockHeld) KeAcquireGuardedMutex(&LpcpLock);
@ -125,10 +125,10 @@ LpcpDestroyPortQueue(IN PLPCP_PORT_OBJECT Port,
{ {
/* Disconnect it */ /* Disconnect it */
Port->ConnectedPort->ConnectedPort = NULL; Port->ConnectedPort->ConnectedPort = NULL;
if (Port->ConnectedPort->ConnectionPort) ConnectionPort = Port->ConnectedPort->ConnectionPort;
if (ConnectionPort)
{ {
/* Save and clear connection port */ /* Clear connection port */
ConnectionPort = Port->ConnectedPort->ConnectionPort;
Port->ConnectedPort->ConnectionPort = NULL; Port->ConnectedPort->ConnectionPort = NULL;
} }
} }
@ -162,7 +162,7 @@ LpcpDestroyPortQueue(IN PLPCP_PORT_OBJECT Port,
if (!KeReadStateSemaphore(&Thread->LpcReplySemaphore)) if (!KeReadStateSemaphore(&Thread->LpcReplySemaphore))
{ {
/* Get the message */ /* Get the message */
Message = Thread->LpcReplyMessage; Message = LpcpGetMessageFromThread(Thread);
if (Message) if (Message)
{ {
/* Check if it's a connection request */ /* Check if it's a connection request */
@ -198,7 +198,7 @@ LpcpDestroyPortQueue(IN PLPCP_PORT_OBJECT Port,
/* Loop queued messages */ /* Loop queued messages */
while ((Port->MsgQueue.ReceiveHead.Flink) && while ((Port->MsgQueue.ReceiveHead.Flink) &&
!(IsListEmpty (&Port->MsgQueue.ReceiveHead))) !(IsListEmpty(&Port->MsgQueue.ReceiveHead)))
{ {
/* Get the message */ /* Get the message */
Message = CONTAINING_RECORD(Port->MsgQueue.ReceiveHead.Flink, Message = CONTAINING_RECORD(Port->MsgQueue.ReceiveHead.Flink,
@ -342,9 +342,6 @@ LpcpDeletePort(IN PVOID ObjectBody)
/* Send it */ /* Send it */
for (;;) for (;;)
{ {
/* FIXME: HACK OF D00m */
break;
/* Send the message */ /* Send the message */
if (LpcRequestPort(Port, if (LpcRequestPort(Port,
&ClientDiedMsg.h) != STATUS_NO_MEMORY) break; &ClientDiedMsg.h) != STATUS_NO_MEMORY) break;

View file

@ -88,7 +88,7 @@ NtAcceptConnectPort(OUT PHANDLE PortHandle,
KeAcquireGuardedMutex(&LpcpLock); KeAcquireGuardedMutex(&LpcpLock);
/* Make sure that the client wants a reply, and this is the right one */ /* Make sure that the client wants a reply, and this is the right one */
if (!(ClientThread->LpcReplyMessage) || if (!(LpcpGetMessageFromThread(ClientThread)) ||
!(ReplyMessage->MessageId) || !(ReplyMessage->MessageId) ||
(ClientThread->LpcReplyMessageId != ReplyMessage->MessageId)) (ClientThread->LpcReplyMessageId != ReplyMessage->MessageId))
{ {
@ -100,7 +100,7 @@ NtAcceptConnectPort(OUT PHANDLE PortHandle,
} }
/* Now get the message and connection message */ /* Now get the message and connection message */
Message = ClientThread->LpcReplyMessage; Message = LpcpGetMessageFromThread(ClientThread);
ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(Message + 1); ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(Message + 1);
/* Get the client and connection port as well */ /* Get the client and connection port as well */
@ -353,7 +353,7 @@ NtCompleteConnectPort(IN HANDLE PortHandle)
Thread = Port->ClientThread; Thread = Port->ClientThread;
/* Make sure it has a reply message */ /* Make sure it has a reply message */
if (!Thread->LpcReplyMessage) if (!LpcpGetMessageFromThread(Thread))
{ {
/* It doesn't, quit */ /* It doesn't, quit */
KeReleaseGuardedMutex(&LpcpLock); KeReleaseGuardedMutex(&LpcpLock);

View file

@ -35,7 +35,7 @@ LpcpFreeConMsg(IN OUT PLPCP_MESSAGE *Message,
} }
/* Check if there's a reply message */ /* Check if there's a reply message */
ReplyMessage = CurrentThread->LpcReplyMessage; ReplyMessage = LpcpGetMessageFromThread(CurrentThread);
if (ReplyMessage) if (ReplyMessage)
{ {
/* Get the message */ /* Get the message */
@ -54,7 +54,7 @@ LpcpFreeConMsg(IN OUT PLPCP_MESSAGE *Message,
CurrentThread->LpcReplyMessage = NULL; CurrentThread->LpcReplyMessage = NULL;
/* Get the connection message and clear the section */ /* Get the connection message and clear the section */
*ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(*Message + 1); *ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(ReplyMessage + 1);
SectionToMap = (*ConnectMessage)->SectionToMap; SectionToMap = (*ConnectMessage)->SectionToMap;
(*ConnectMessage)->SectionToMap = NULL; (*ConnectMessage)->SectionToMap = NULL;
} }

View file

@ -279,12 +279,10 @@ NtReplyWaitReceivePortEx(IN HANDLE PortHandle,
KeAcquireGuardedMutex(&LpcpLock); KeAcquireGuardedMutex(&LpcpLock);
/* Make sure this is the reply the thread is waiting for */ /* Make sure this is the reply the thread is waiting for */
if ((WakeupThread->LpcReplyMessageId != ReplyMessage->MessageId))// || if ((WakeupThread->LpcReplyMessageId != ReplyMessage->MessageId) ||
#if 0 ((LpcpGetMessageFromThread(WakeupThread)) &&
((WakeupThread->LpcReplyMessage) && (LpcpGetMessageType(&LpcpGetMessageFromThread(WakeupThread)->
(LpcpGetMessageType(&((PLPCP_MESSAGE)WakeupThread-> Request) != LPC_REQUEST)))
LpcReplyMessage)->Request) != LPC_REQUEST)))
#endif
{ {
/* It isn't, fail */ /* It isn't, fail */
LpcpFreeToPortZone(Message, 3); LpcpFreeToPortZone(Message, 3);

View file

@ -155,8 +155,8 @@ LpcRequestPort(IN PVOID PortObject,
/* We're done */ /* We're done */
KeLeaveCriticalRegion(); KeLeaveCriticalRegion();
LPCTRACE(LPC_SEND_DEBUG, "Port: %p. Message: %p\n", QueuePort, Message);
if (ConnectionPort) ObDereferenceObject(ConnectionPort); if (ConnectionPort) ObDereferenceObject(ConnectionPort);
LPCTRACE(LPC_SEND_DEBUG, "Port: %p. Message: %p\n", QueuePort, Message);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -366,7 +366,7 @@ NtRequestWaitReplyPort(IN HANDLE PortHandle,
/* Insert the message in our chain */ /* Insert the message in our chain */
InsertTailList(&QueuePort->MsgQueue.ReceiveHead, &Message->Entry); InsertTailList(&QueuePort->MsgQueue.ReceiveHead, &Message->Entry);
InsertTailList(&ReplyPort->LpcReplyChainHead, &Thread->LpcReplyChain); InsertTailList(&ReplyPort->LpcReplyChainHead, &Thread->LpcReplyChain);
Thread->LpcWaitingOnPort = Port; LpcpSetPortToThread(Thread, Port);
/* Release the lock and get the semaphore we'll use later */ /* Release the lock and get the semaphore we'll use later */
KeEnterCriticalRegion(); KeEnterCriticalRegion();
@ -392,7 +392,7 @@ NtRequestWaitReplyPort(IN HANDLE PortHandle,
KeAcquireGuardedMutex(&LpcpLock); KeAcquireGuardedMutex(&LpcpLock);
/* Get the LPC Message and clear our thread's reply data */ /* Get the LPC Message and clear our thread's reply data */
Message = Thread->LpcReplyMessage; Message = LpcpGetMessageFromThread(Thread);
Thread->LpcReplyMessage = NULL; Thread->LpcReplyMessage = NULL;
Thread->LpcReplyMessageId = 0; Thread->LpcReplyMessageId = 0;