333 lines
7.8 KiB
C
333 lines
7.8 KiB
C
|
/*++
|
|||
|
|
|||
|
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 <zwapi.h>
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// 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 {
|
|||
|
|
|||
|
FAST_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() \
|
|||
|
{ \
|
|||
|
ExInitializeFastMutex( &LpcpLock.Lock ); \
|
|||
|
LpcpLock.Owner = NULL; \
|
|||
|
}
|
|||
|
|
|||
|
#define LpcpAcquireLpcpLock() \
|
|||
|
{ \
|
|||
|
ASSERT ( LpcpLock.Owner != PsGetCurrentThread() ); \
|
|||
|
\
|
|||
|
ExAcquireFastMutex( &LpcpLock.Lock ); \
|
|||
|
LpcpLock.Owner = PsGetCurrentThread(); \
|
|||
|
}
|
|||
|
|
|||
|
#define LpcpAcquireLpcpLockByThread(Thread) \
|
|||
|
{ \
|
|||
|
ASSERT ( LpcpLock.Owner != PsGetCurrentThread() ); \
|
|||
|
\
|
|||
|
ExAcquireFastMutex( &LpcpLock.Lock ); \
|
|||
|
LpcpLock.Owner = Thread; \
|
|||
|
}
|
|||
|
|
|||
|
#define LpcpReleaseLpcpLock() \
|
|||
|
{ \
|
|||
|
ASSERT( LpcpLock.Owner == PsGetCurrentThread() ); \
|
|||
|
\
|
|||
|
LpcpLock.Owner = NULL; \
|
|||
|
ExReleaseFastMutex( &LpcpLock.Lock ); \
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Internal Entry Points defined in lpcclose.c
|
|||
|
//
|
|||
|
|
|||
|
VOID
|
|||
|
LpcpClosePort (
|
|||
|
IN PEPROCESS Process OPTIONAL,
|
|||
|
IN PVOID Object,
|
|||
|
IN ACCESS_MASK GrantedAccess,
|
|||
|
IN ULONG ProcessHandleCount,
|
|||
|
IN ULONG 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
|
|||
|
);
|
|||
|
|
|||
|
PLPCP_MESSAGE
|
|||
|
LpcpFindDataInfoMessage (
|
|||
|
IN PLPCP_PORT_OBJECT Port,
|
|||
|
IN ULONG MessageId,
|
|||
|
IN ULONG CallbackId
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// 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 LPC_PORT_MASK_BIT 1
|
|||
|
|
|||
|
#define LpcpGetThreadMessage(T) \
|
|||
|
( \
|
|||
|
(((ULONG_PTR)(T)->LpcReplyMessage) & LPC_PORT_MASK_BIT) ? NULL : (PLPCP_MESSAGE)(T)->LpcReplyMessage \
|
|||
|
)
|
|||
|
|
|||
|
#define LpcpGetThreadPort(T) \
|
|||
|
( \
|
|||
|
(((ULONG_PTR)(T)->LpcReplyMessage) & LPC_PORT_MASK_BIT) ? \
|
|||
|
(PLPCP_PORT_OBJECT)(((ULONG_PTR)(T)->LpcWaitingOnPort) & ~LPC_PORT_MASK_BIT): \
|
|||
|
NULL \
|
|||
|
)
|
|||
|
|
|||
|
#define LpcpSetPortToThread(T,P) \
|
|||
|
(T)->LpcWaitingOnPort = (PVOID)(((ULONG_PTR)P) | LPC_PORT_MASK_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
|
|||
|
);
|
|||
|
|