windows-nt/Source/XPSP1/NT/com/rpc/runtime/mtrt/util.hxx
2020-09-26 16:20:57 +08:00

803 lines
16 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1990 - 1999
//
// File: util.hxx
//
//--------------------------------------------------------------------------
/* --------------------------------------------------------------------
Internal Header File for RPC Runtime Library
-------------------------------------------------------------------- */
#ifndef __UTIL_HXX__
#define __UTIL_HXX__
#ifndef __SYSINC_H__
#error Needs sysinc.h
#endif
START_C_EXTERN
#ifndef ARGUMENT_PRESENT
#define ARGUMENT_PRESENT(Argument) (Argument != 0)
#endif // ARGUMENT_PRESENT
#ifdef NULL
#undef NULL
#endif
#define NULL (0)
#define Nil 0
#ifdef TRUE
#undef TRUE
#endif
#ifdef FALSE
#undef FALSE
#endif
#define _NOT_COVERED_ (0)
#define FALSE (0)
#define TRUE (1)
//
// Expose the external logging hook on all builds.
//
#define RPC_ENABLE_WMI_TRACE
#define RPC_ERROR_LOGGING
#ifdef DBG
//#define RPC_ENABLE_TEST_HOOKS
#ifndef RPC_LOGGING
#define RPC_LOGGING
#endif
#endif
unsigned long
SomeLongValue (
);
unsigned short
SomeShortValue (
);
unsigned short
AnotherShortValue (
);
unsigned char
SomeCharacterValue (
);
extern int
RpcpCheckHeap (
void
);
int
IsMgmtIfUuid(
UUID PAPI * Uuid
);
END_C_EXTERN
void
PerformGarbageCollection (
void
);
BOOL
GarbageCollectionNeeded (
IN BOOL fOneTimeCleanup,
IN unsigned long GarbageCollectInterval
);
RPC_STATUS CreateGarbageCollectionThread (
void
);
RPC_STATUS
EnableIdleConnectionCleanup (
void
);
RPC_STATUS
EnableIdleLrpcSContextsCleanup (
void
);
void
GetMaxRpcSizeAndThreadPoolParameters (
void
);
#ifdef RPC_DELAYED_INITIALIZATION
extern int RpcHasBeenInitialized;
extern RPC_STATUS
PerformRpcInitialization (
void
);
#define InitializeIfNecessary() \
if ( RpcHasBeenInitialized == 0 ) \
{ \
RPC_STATUS RpcStatus; \
\
RpcStatus = PerformRpcInitialization(); \
if ( RpcStatus != RPC_S_OK ) \
return(RpcStatus); \
}
#define AssertRpcInitialized() ASSERT( RpcHasBeenInitialized != 0 )
#else /* RPC_DELAYED_INITIALIZATION */
#define InitializeIfNecessary()
#define AssertRpcInitialized()
#define PerformRpcInitialization()
#endif /* RPC_DELAYED_INITIALIZATION */
RPC_CHAR *
DuplicateString (
IN RPC_CHAR PAPI * String
);
#ifdef UNICODE
extern RPC_STATUS
AnsiToUnicodeString (
IN unsigned char * String,
OUT UNICODE_STRING * UnicodeString
);
extern unsigned char *
UnicodeToAnsiString (
IN RPC_CHAR * WideCharString,
OUT RPC_STATUS * RpcStatus
);
#endif // UNICODE
void
DestroyContextHandlesForGuard (
IN PVOID Context,
IN BOOL RundownContextHandle,
IN void *CtxGuard
);
// forward definition
class ContextCollection;
RPC_STATUS
NDRSContextInitializeCollection (
IN ContextCollection **ContextCollectionPlaceholder
);
#if DBG
void
RpcpInterfaceForCallDoesNotUseStrict (
IN RPC_BINDING_HANDLE BindingHandle
);
#endif
inline unsigned short
RpcpByteSwapShort (unsigned short Value)
{
return (RtlUshortByteSwap(Value));
}
inline unsigned long
RpcpByteSwapLong (unsigned long Value)
{
return (RtlUlongByteSwap(Value));
}
typedef union tagFastCopyLUIDAccess
{
LUID Luid;
__int64 FastAccess;
} FastCopyLUIDAccess;
inline void FastCopyLUIDAligned (LUID *TargetLUID, const LUID *SourceLUID)
{
FastCopyLUIDAccess *EffectiveSourceLUID = (FastCopyLUIDAccess *)SourceLUID;
FastCopyLUIDAccess *EffectiveTargetLUID = (FastCopyLUIDAccess *)TargetLUID;
#if defined(_WIN64)
ASSERT((((ULONG_PTR)EffectiveSourceLUID) % 8) == 0);
ASSERT((((ULONG_PTR)EffectiveTargetLUID) % 8) == 0);
#endif
EffectiveTargetLUID->FastAccess = EffectiveSourceLUID->FastAccess;
}
inline void FastCopyLUID (LUID *TargetLUID, LUID *SourceLUID)
{
FastCopyLUIDAccess *EffectiveSourceLUID = (FastCopyLUIDAccess *)SourceLUID;
FastCopyLUIDAccess *EffectiveTargetLUID = (FastCopyLUIDAccess *)TargetLUID;
#if !defined(_WIN64)
FastCopyLUIDAligned(TargetLUID, SourceLUID);
#else
TargetLUID->HighPart = SourceLUID->HighPart;
TargetLUID->LowPart = SourceLUID->LowPart;
#endif
}
// returns non-zero if equal
inline BOOL FastCompareLUIDAligned (const LUID *TargetLUID, const LUID *SourceLUID)
{
FastCopyLUIDAccess *EffectiveSourceLUID = (FastCopyLUIDAccess *)SourceLUID;
FastCopyLUIDAccess *EffectiveTargetLUID = (FastCopyLUIDAccess *)TargetLUID;
#if defined(_WIN64)
ASSERT((((ULONG_PTR)EffectiveSourceLUID) % 8) == 0);
ASSERT((((ULONG_PTR)EffectiveTargetLUID) % 8) == 0);
#endif
return (EffectiveTargetLUID->FastAccess == EffectiveSourceLUID->FastAccess);
}
inline BOOL FastCompareLUID (LUID *TargetLUID, LUID *SourceLUID)
{
FastCopyLUIDAccess *EffectiveSourceLUID = (FastCopyLUIDAccess *)SourceLUID;
FastCopyLUIDAccess *EffectiveTargetLUID = (FastCopyLUIDAccess *)TargetLUID;
#if !defined(_WIN64)
return FastCompareLUIDAligned(TargetLUID, SourceLUID);
#else
return ((TargetLUID->HighPart == SourceLUID->HighPart)
&& (TargetLUID->LowPart == SourceLUID->LowPart));
#endif
}
const RPC_CHAR *
FastGetImageBaseName (
void
);
//
// System features - constant after InitializeIfNecessary.
//
// Just contants on non-NT systems
//
extern DWORD gPageSize;
extern DWORD gThreadTimeout;
extern UINT gNumberOfProcessors;
extern DWORD gMaxRpcSize;
extern DWORD gProrateStart;
extern DWORD gProrateMax;
extern DWORD gProrateFactor;
extern BOOL gfServerPlatform;
extern ULONGLONG gPhysicalMemorySize; // in megabytes
// if non-zero, we're in paged bcache (paged buffers mode)
extern BOOL fPagedBCacheMode;
// if non-zero, we may be in lsa. This is maybe, because
// conclusive check is too expensive, and the only
// way we use this flag is to avoid some optimizations
// that can result in deadlock in lsa.
extern BOOL fMaybeLsa;
//
// constants for LogEvent(),
//
#define SU_HANDLE 'h'
#define SU_CCONN 'n'
#define SU_SCONN 'N'
#define SU_CASSOC 'a'
#define SU_SASSOC 'A'
#define SU_CCALL 'c'
#define SU_SCALL 'C'
#define SU_PACKET 'p'
#define SU_CENDPOINT 'e'
#define SU_ENGINE 'E'
#define SU_ASSOC '.'
#define SU_MUTEX 'm'
#define SU_STABLE 'T'
#define SU_ADDRESS 'D'
#define SU_HEAP 'H'
#define SU_BCACHE 'b'
#define SU_REFOBJ 'r'
#define SU_THREAD 't'
#define SU_TRANS_CONN 'o'
#define SU_EVENT 'v'
#define SU_EXCEPT 'x'
#define SU_CTXHANDLE 'l'
#define SU_EEINFO 'I'
#define SU_GC 'G'
#define SU_HTTPv2 '2'
#define EV_CREATE 'C'
#define EV_DELETE 'D'
#define EV_START 'c'
#define EV_STOP 'd'
#define EV_INC '+'
#define EV_DEC '-'
#define EV_PROC 'p'
#define EV_ACK 'a'
#define EV_CALLBACK 'L'
#define EV_NOTIFY 'N'
#define EV_APC 'A'
#define EV_STATUS 'S'
#define EV_DISASSOC 'x'
#define EV_STATE '='
#define EV_POP 'P'
#define EV_PUSH 'Q'
#define EV_PKT_IN 'k'
#define EV_PKT_OUT 'K'
#define EV_BUFFER_IN 'b'
#define EV_BUFFER_OUT 'B'
#define EV_BUFFER_FAIL 'X'
#define EV_ABORT 'R'
#define EV_SET 's'
// for debugging. A packet can be dropped or delayed.
//
#define EV_DROP '*'
#define EV_DELAY '#'
#define EV_PRUNE 'p'
// SU_SCONN: a call is being transferred to another connection during auto-reconnect.
//
#define EV_TRANSFER 'T'
// SU_CASSOC: the dynamic endpoint has been resolved into a real endpoint
//
#define EV_RESOLVED 'r'
// SU_ENGINE: window size and selective-ack bits from a FACK or NOCALL
//
#define EV_WINDOW 'w'
// SU_SCALL: the call was removed from the connection's active list
#define EV_REMOVED 'm'
// SU_SCALL: Cleanup() was called with refcount > 0
#define EV_CLEANUP ','
#define EV_BHCOPY 'O'
#define EV_ALLOCATE 't'
#define EV_OPER 'o'
//
//
#define EV_SEC_INIT1 'i'
#define EV_SEC_INIT3 'I'
#define EV_SEC_ACCEPT1 'j'
#define EV_SEC_ACCEPT3 'J'
#define IN_CHANNEL_STATE (UlongToPtr(0))
#define OUT_CHANNEL_STATE (UlongToPtr(1))
#define MAX_RPC_EVENT 4096
#define STACKTRACE_DEPTH 4
struct RPC_EVENT
{
DWORD Thread;
DWORD Time;
unsigned char Subject;
unsigned char Verb;
void * SubjectPointer;
void * ObjectPointer;
ULONG_PTR Data;
void * EventStackTrace[STACKTRACE_DEPTH];
};
extern void
TrulyLogEvent(
IN unsigned char Subject,
IN unsigned char Verb,
IN void * SubjectPointer,
IN void * ObjectPointer = 0,
IN ULONG_PTR Data = 0,
IN BOOL fCaptureStackTrace = 0,
IN int AdditionalFramesToSkip = 0
);
#ifdef RPC_LOGGING
extern BOOL fEnableLog;
inline void
LogEvent(
IN unsigned char Subject,
IN unsigned char Verb,
IN void * SubjectPointer,
IN void * ObjectPointer = 0,
IN ULONG_PTR Data = 0,
IN BOOL fCaptureStackTrace = 0,
IN int AdditionalFramesToSkip = 0
)
{
if (fEnableLog)
{
TrulyLogEvent( Subject,
Verb,
SubjectPointer,
ObjectPointer,
Data,
fCaptureStackTrace,
AdditionalFramesToSkip
);
}
}
#else
inline void
LogEvent(
IN unsigned char Subject,
IN unsigned char Verb,
IN void * SubjectPointer,
IN void * ObjectPointer = 0,
IN ULONG_PTR Data = 0,
IN BOOL fCaptureStackTrace = 0,
IN int AdditionalFramesToSkip = 0
)
{
#if DBG
TrulyLogEvent(Subject, Verb, SubjectPointer, ObjectPointer, Data, fCaptureStackTrace,
AdditionalFramesToSkip);
#endif
}
#endif
//
// LogError will produce an event even on normal retail builds.
//
#ifdef RPC_ERROR_LOGGING
inline void
LogError(
IN unsigned char Subject,
IN unsigned char Verb,
IN void * SubjectPointer,
IN void * ObjectPointer = 0,
IN ULONG_PTR Data = 0,
IN BOOL fCaptureStackTrace = 0,
IN int AdditionalFramesToSkip = 0
)
{
TrulyLogEvent( Subject,
Verb,
SubjectPointer,
ObjectPointer,
Data,
fCaptureStackTrace,
AdditionalFramesToSkip
);
}
#else
inline void
LogError(
IN unsigned char Subject,
IN unsigned char Verb,
IN void * SubjectPointer,
IN void * ObjectPointer = 0,
IN ULONG_PTR Data = 0,
IN BOOL fCaptureStackTrace = 0,
IN int AdditionalFramesToSkip = 0
)
{
#if DBG
TrulyLogEvent(Subject, Verb, SubjectPointer, ObjectPointer, Data, fCaptureStackTrace,
AdditionalFramesToSkip);
#endif
}
#endif
#ifdef STATS
extern DWORD g_dwStat1;
extern DWORD g_dwStat2;
extern DWORD g_dwStat3;
extern DWORD g_dwStat4;
inline void GetStats(DWORD *pdwStat1, DWORD *pdwStat2, DWORD *pdwStat3, DWORD *pdwStat4)
{
*pdwStat1 = g_dwStat1;
*pdwStat2 = g_dwStat2;
*pdwStat3 = g_dwStat3;
*pdwStat4 = g_dwStat4;
}
inline void SetStat1(DWORD dwStat)
{
g_dwStat1 = dwStat;
}
inline void SetStat2(DWORD dwStat)
{
g_dwStat2 = dwStat;
}
inline void SetStat3(DWORD dwStat)
{
g_dwStat3 = dwStat;
}
inline void SetStat4(DWORD dwStat)
{
g_dwStat4 = dwStat;
}
inline void IncStat1(void)
{
InterlockedIncrement((long *) &g_dwStat1);
}
inline void DecStat1(void)
{
InterlockedDecrement((long *) &g_dwStat1);
}
inline void Stat1Add(long val)
{
InterlockedExchangeAdd((long *) &g_dwStat1, val);
}
inline void Stat1Sub(long val)
{
InterlockedExchangeAdd((long *) &g_dwStat1, -val);
}
inline void IncStat2(void)
{
InterlockedIncrement((long *) &g_dwStat2);
}
inline void DecStat2(void)
{
InterlockedDecrement((long *) &g_dwStat2);
}
inline void Stat2Add(long val)
{
InterlockedExchangeAdd((long *) &g_dwStat2, val);
}
inline void Stat2Sub(long val)
{
InterlockedExchangeAdd((long *) &g_dwStat2, -val);
}
inline void IncStat3(void)
{
InterlockedIncrement((long *) &g_dwStat3);
}
inline void DecStat3(void)
{
InterlockedDecrement((long *) &g_dwStat3);
}
inline void Stat3Add(long val)
{
InterlockedExchangeAdd((long *) &g_dwStat3, val);
}
inline void Stat3Sub(long val)
{
InterlockedExchangeAdd((long *) &g_dwStat3, -val);
}
inline void IncStat4(void)
{
InterlockedIncrement((long *) &g_dwStat4);
}
inline void DecStat4(void)
{
InterlockedDecrement((long *) &g_dwStat4);
}
inline void Stat4Add(long val)
{
InterlockedExchangeAdd((long *) &g_dwStat4, val);
}
inline void Stat4Sub(long val)
{
InterlockedExchangeAdd((long *) &g_dwStat4, -val);
}
#else
inline void GetStats(DWORD *pdwStat1, DWORD *pdwStat2, DWORD *pdwStat3, DWORD *pdwStat4)
{
}
inline void SetStat1(DWORD dwStat)
{
}
inline void SetStat2(DWORD dwStat)
{
}
inline void SetStat3(DWORD dwStat)
{
}
inline void SetStat4(DWORD dwStat)
{
}
inline void IncStat1(void)
{
}
inline void DecStat1(void)
{
}
inline void Stat1Add(long val)
{
}
inline void Stat1Sub(long val)
{
}
inline void IncStat2(void)
{
}
inline void DecStat2(void)
{
}
inline void Stat2Add(long val)
{
}
inline void Stat2Sub(long val)
{
}
inline void IncStat3(void)
{
}
inline void DecStat3(void)
{
}
inline void Stat3Add(long val)
{
}
inline void Stat3Sub(long val)
{
}
inline void IncStat4(void)
{
}
inline void DecStat4(void)
{
}
inline void Stat4Add(long val)
{
}
inline void Stat4Sub(long val)
{
}
#endif
//
// test hook data. The stuff that would logically live in UTIL.CXX is actually in DGCLNT.CXX
// due to trouble linking the BVT programs.
//
typedef unsigned long RPC_TEST_HOOK_ID;
typedef void (RPC_TEST_HOOK_FN_RAW)( RPC_TEST_HOOK_ID id, PVOID subject, PVOID object );
typedef RPC_TEST_HOOK_FN_RAW * RPC_TEST_HOOK_FN;
RPCRTAPI
DWORD
RPC_ENTRY
I_RpcSetTestHook(
RPC_TEST_HOOK_ID id,
RPC_TEST_HOOK_FN fn
);
void
ForceCallTestHook(
RPC_TEST_HOOK_ID id,
PVOID subject,
PVOID object
);
//
// ranges for the major field:
//
// common: 001-099
// dg: 100-199
// co: 200-299
// lrpc: 300-399
// transports: 400-499
// reserved: 500-32767
//
#define MAKE_TEST_HOOK_ID( major, minor ) ( ((major) << 16) | (minor) )
#define TH_RPC_BASE 1
#define TH_DG_BASE 100
#define TH_CO_BASE 200
#define TH_LRPC_BASE 300
#define TH_TRANS_BASE 400
//
// protocol-independent hook IDs.
//
// member functions of SECURITY_CONTEXT and SECURITY_CREDENTIALS
//
#define TH_SECURITY_PROVIDER (TH_RPC_BASE+1)
//
// Each of these hooks is passed the security context and a pStatus pointer.
// If the hook makes *pStatus nonzero, that becomes the return code from the
// member function.
//
#define TH_SECURITY_FN_SIGN MAKE_TEST_HOOK_ID( TH_SECURITY_PROVIDER, 1)
#define TH_SECURITY_FN_VERIFY MAKE_TEST_HOOK_ID( TH_SECURITY_PROVIDER, 2)
#define TH_SECURITY_FN_ACCEPT1 MAKE_TEST_HOOK_ID( TH_SECURITY_PROVIDER, 3)
#define TH_SECURITY_FN_ACCEPT3 MAKE_TEST_HOOK_ID( TH_SECURITY_PROVIDER, 4)
#define TH_SECURITY_FN_INIT1 MAKE_TEST_HOOK_ID( TH_SECURITY_PROVIDER, 5)
#define TH_SECURITY_FN_INIT3 MAKE_TEST_HOOK_ID( TH_SECURITY_PROVIDER, 6)
#define TH_RPC_SECURITY_SERVER_CONTEXT_CREATED MAKE_TEST_HOOK_ID( TH_SECURITY_PROVIDER, 7)
#define TH_RPC_SECURITY_CLIENT_CONTEXT_CREATED MAKE_TEST_HOOK_ID( TH_SECURITY_PROVIDER, 8)
// subject = pointer to RPC event structure
// object = 0
//
#define TH_RPC_LOG_EVENT MAKE_TEST_HOOK_ID(TH_RPC_BASE+2, 1)
inline void
CallTestHook(
RPC_TEST_HOOK_ID id,
PVOID subject = 0,
PVOID object = 0
)
{
#ifdef RPC_ENABLE_TEST_HOOKS
ForceCallTestHook( id, subject, object );
#endif
}
#ifdef RPC_ENABLE_TEST_HOOKS
RPC_TEST_HOOK_FN
GetTestHook(
RPC_TEST_HOOK_ID id
);
#endif
#endif /* __UTIL_HXX__ */