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=2... ============================================================================== --- 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/l... ============================================================================== --- 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/l... ============================================================================== --- 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=25... ============================================================================== --- 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?rev... ============================================================================== --- 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=25... ============================================================================== --- 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=255... ============================================================================== --- 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;