|
|
//+-------------------------------------------------------------------------
//
// 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__ */
|