/*++ Copyright (c) 1989 Microsoft Corporation Module Name: lpcp.h Abstract: Private include file for the LPC subcomponent of the NTOS project Author: Steve Wood (stevewo) 15-May-1989 Revision History: --*/ #pragma warning(disable:4214) // bit field types other than int #pragma warning(disable:4201) // nameless struct/union #pragma warning(disable:4324) // alignment sensitive to declspec #pragma warning(disable:4127) // condition expression is constant #pragma warning(disable:4115) // named type definition in parentheses #pragma warning(disable:4310) // cast truncates constant value #include "ntos.h" #include //#define _LPC_LOG_ERRORS // // Global Mutex to guard the following fields: // // ETHREAD.LpcReplyMsg // LPCP_PORT_QUEUE.ReceiveHead // // Mutex is never held longer than is necessary to modify or read the field. // Contains an additional field to track the owner of the mutex. // typedef struct _LPC_MUTEX { KGUARDED_MUTEX Lock; // // field that holds the thread that owns the lock // PETHREAD Owner; } LPC_MUTEX, *PLPC_MUTEX; extern LPC_MUTEX LpcpLock; extern ULONG LpcpMaxMessageSize; #define LpcpGetMaxMessageLength() (LpcpMaxMessageSize) extern ULONG LpcpNextMessageId; extern ULONG LpcpNextCallbackId; #define LpcpGenerateMessageId() \ LpcpNextMessageId++; if (LpcpNextMessageId == 0) LpcpNextMessageId = 1; #define LpcpGenerateCallbackId() \ LpcpNextCallbackId++; if (LpcpNextCallbackId == 0) LpcpNextCallbackId = 1; extern ULONG LpcpTotalNumberOfMessages; // // Global macrodefinitions to acquire and release the LPC_MUTEX // in order to track the owner and allow recursive calls // #define LpcpInitializeLpcpLock() \ { \ KeInitializeGuardedMutex( &LpcpLock.Lock ); \ LpcpLock.Owner = NULL; \ } #define LpcpAcquireLpcpLock() \ { \ ASSERT ( LpcpLock.Owner != PsGetCurrentThread() ); \ \ KeAcquireGuardedMutex( &LpcpLock.Lock ); \ LpcpLock.Owner = PsGetCurrentThread(); \ } #define LpcpAcquireLpcpLockByThread(Thread) \ { \ ASSERT ( LpcpLock.Owner != PsGetCurrentThread() ); \ \ KeAcquireGuardedMutex( &LpcpLock.Lock ); \ LpcpLock.Owner = Thread; \ } #define LpcpReleaseLpcpLock() \ { \ ASSERT( LpcpLock.Owner == PsGetCurrentThread() ); \ \ LpcpLock.Owner = NULL; \ KeReleaseGuardedMutex( &LpcpLock.Lock ); \ } // // Internal Entry Points defined in lpcclose.c // VOID LpcpClosePort ( IN PEPROCESS Process OPTIONAL, IN PVOID Object, IN ACCESS_MASK GrantedAccess, IN ULONG_PTR ProcessHandleCount, IN ULONG_PTR SystemHandleCount ); VOID LpcpDeletePort ( IN PVOID Object ); // // Entry points defined in lpcqueue.c // NTSTATUS LpcpInitializePortQueue ( IN PLPCP_PORT_OBJECT Port ); VOID LpcpDestroyPortQueue ( IN PLPCP_PORT_OBJECT Port, IN BOOLEAN CleanupAndDestroy ); VOID LpcpInitializePortZone ( IN ULONG MaxEntrySize ); NTSTATUS LpcpExtendPortZone ( VOID ); VOID LpcpSaveDataInfoMessage ( IN PLPCP_PORT_OBJECT Port, IN PLPCP_MESSAGE Msg, IN ULONG MutexFlags ); VOID LpcpFreeDataInfoMessage ( IN PLPCP_PORT_OBJECT Port, IN ULONG MessageId, IN ULONG CallbackId, IN LPC_CLIENT_ID ClientId ); PLPCP_MESSAGE LpcpFindDataInfoMessage ( IN PLPCP_PORT_OBJECT Port, IN ULONG MessageId, IN ULONG CallbackId, IN LPC_CLIENT_ID ClientId ); // // Entry points defined in lpcquery.c // // // Entry points defined in lpcmove.s and lpcmove.asm // VOID LpcpMoveMessage ( OUT PPORT_MESSAGE DstMsg, IN PPORT_MESSAGE SrcMsg, IN PVOID SrcMsgData, IN ULONG MsgType OPTIONAL, IN PCLIENT_ID ClientId OPTIONAL ); // // Internal Entry Points defined in lpcpriv.c // VOID LpcpFreePortClientSecurity ( IN PLPCP_PORT_OBJECT Port ); // // Macro Procedures used by RequestWaitReply, Reply, ReplyWaitReceive, // and ReplyWaitReply services // #define LpcpGetDynamicClientSecurity(Thread,Port,DynamicSecurity) \ SeCreateClientSecurity((Thread),&(Port)->SecurityQos,FALSE,(DynamicSecurity)) #define LpcpFreeDynamicClientSecurity(DynamicSecurity) \ SeDeleteClientSecurity( DynamicSecurity ) #define LpcpReferencePortObject(PortHandle,PortAccess,PreviousMode,PortObject) \ ObReferenceObjectByHandle((PortHandle),(PortAccess),LpcPortObjectType,(PreviousMode),(PVOID *)(PortObject),NULL) #define LPCP_PORT_BIT 1 #define LPCP_NO_IMPERSONATION 2 #define LPCP_THREAD_ATTRIBUTES (LPCP_PORT_BIT | LPCP_NO_IMPERSONATION) #define LpcpGetThreadMessage(T) \ ( \ (((ULONG_PTR)(T)->LpcReplyMessage) & LPCP_PORT_BIT) ? NULL : \ (PLPCP_MESSAGE)((ULONG_PTR)(T)->LpcReplyMessage & ~LPCP_THREAD_ATTRIBUTES) \ ) #define LpcpGetThreadPort(T) \ ( \ (((ULONG_PTR)(T)->LpcReplyMessage) & LPCP_PORT_BIT) ? \ (PLPCP_PORT_OBJECT)(((ULONG_PTR)(T)->LpcWaitingOnPort) & ~LPCP_THREAD_ATTRIBUTES): \ NULL \ ) #define LpcpGetThreadAttributes(T) \ (((ULONG_PTR)(T)->LpcWaitingOnPort) & LPCP_THREAD_ATTRIBUTES) #define LpcpSetThreadAttributes(T,A) \ (T)->LpcWaitingOnPort = (PVOID)(((ULONG_PTR)(T)->LpcWaitingOnPort) | (A)); #define LpcpSetPortToThread(T,P) \ (T)->LpcWaitingOnPort = (PVOID)(((ULONG_PTR)P) | LPCP_PORT_BIT); #define LPCP_VALIDATE_REASON_IMPERSONATION 1 #define LPCP_VALIDATE_REASON_REPLY 2 #define LPCP_VALIDATE_REASON_WRONG_DATA 3 BOOLEAN FASTCALL LpcpValidateClientPort( IN PETHREAD Thread, IN PLPCP_PORT_OBJECT ReplyPort, IN ULONG Reason ); // // Entry Points defined in lpcinit.c // #if DBG #define ENABLE_LPC_TRACING 1 #else #define ENABLE_LPC_TRACING 0 #endif #if ENABLE_LPC_TRACING BOOLEAN LpcpStopOnReplyMismatch; BOOLEAN LpcpTraceMessages; char *LpcpMessageTypeName[]; char * LpcpGetCreatorName ( PLPCP_PORT_OBJECT PortObject ); #define LpcpPrint( _x_ ) { \ DbgPrint( "LPC[ %02x.%02x ]: ", \ PsGetCurrentThread()->Cid.UniqueProcess, \ PsGetCurrentThread()->Cid.UniqueThread ); \ DbgPrint _x_ ; \ } #define LpcpTrace( _x_ ) if (LpcpTraceMessages) { LpcpPrint( _x_ ); } #else #define LpcpPrint( _x_ ) #define LpcpTrace( _x_ ) #endif // ENABLE_LPC_TRACING extern PAGED_LOOKASIDE_LIST LpcpMessagesLookaside; __forceinline PLPCP_MESSAGE LpcpAllocateFromPortZone ( ULONG Size ) { PLPCP_MESSAGE Msg; PAGED_CODE(); UNREFERENCED_PARAMETER (Size); Msg = ExAllocateFromPagedLookasideList( &LpcpMessagesLookaside ); if (Msg != NULL) { LpcpTrace(( "Allocate Msg %lx\n", Msg )); InitializeListHead( &Msg->Entry ); Msg->RepliedToThread = NULL; // // Clear the message type field. In some failure paths this message get freed // w/o having it initialized. // Msg->Request.u2.s2.Type = 0; return Msg; } return NULL; } #define LPCP_MUTEX_OWNED 0x1 #define LPCP_MUTEX_RELEASE_ON_RETURN 0x2 VOID FASTCALL LpcpFreeToPortZone ( IN PLPCP_MESSAGE Msg, IN ULONG MutexFlags ); #ifdef _LPC_LOG_ERRORS extern NTSTATUS LpcpLogErrorFilter; VOID LpcpInitilizeLogging(); VOID LpcpLogEntry ( NTSTATUS Status, CLIENT_ID ClientId, PPORT_MESSAGE PortMessage ); __forceinline VOID LpcpTraceError ( NTSTATUS Status, CLIENT_ID ClientId, PPORT_MESSAGE PortMessage ) { if ((LpcpLogErrorFilter == 0) || (LpcpLogErrorFilter == Status)) { LpcpLogEntry( Status, ClientId, PortMessage); } } #else // _LPC_LOG_ERRORS #define LpcpInitilizeLogging() #define LpcpLogEntry(_Status_,_ClientId_,_PortMessage_) #define LpcpTraceError(_Status_,_ClientId_,_PortMessage_) #endif // _LPC_LOG_ERRORS