- 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;
//
// 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

View file

@ -47,6 +47,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
//

View file

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

View 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;

View 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);

View 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;
}

View 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);

View 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;