mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
- 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:
parent
a0d7a72c1a
commit
d1c966119b
8 changed files with 72 additions and 33 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
//
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in a new issue