|
|
//+-------------------------------------------------------------------------
//
// 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 const RPC_CHAR PAPI * String );
PSID DuplicateSID ( IN const PSID Sid );
// trick the compiler into statically initializing SID with two SubAuthorities
typedef struct _RPC_SID2 { UCHAR Revision; UCHAR SubAuthorityCount; SID_IDENTIFIER_AUTHORITY IdentifierAuthority; ULONG SubAuthority[2]; } RPC_SID2;
extern const SID LocalSystem; extern const SID LocalService; extern const SID NetworkService; extern const RPC_SID2 Admin1;
RPC_STATUS RpcpLookupAccountName ( IN RPC_CHAR *ServerPrincipalName, IN OUT BOOL *fCache, OUT PSID *Sid );
RPC_STATUS RpcpLookupAccountNameDirect ( IN RPC_CHAR *ServerPrincipalName, OUT PSID *Sid );
RPC_STATUS RpcpLookupAccountSid ( IN PSID Sid, OUT RPC_CHAR **ServerPrincipalName );
#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
}
// zeroes out everything b/n the two fields, including the first field,
// but excluding the second
#define RPCP_ZERO_OUT_STRUCT_RANGE(Type, Instance, Field1, Field2) \
RpcpMemorySet(((char *)(Instance)) + FIELD_OFFSET(Type, Field1), 0, FIELD_OFFSET(Type, Field2) - FIELD_OFFSET(Type, Field1))
// zeroes out everything from a field to the end including the field
#define RPCP_ZERO_OUT_STRUCT_TAIL(Type, Instance, Field) \
RpcpMemorySet(((char *)(Instance)) + FIELD_OFFSET(Type, Field), 0, sizeof(Type) - FIELD_OFFSET(Type, Field))
PUNICODE_STRING FastGetImageBaseNameUnicodeString ( void );
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
extern DWORD gProcessStartTime;
// The local machine's name.
extern RPC_CHAR *gLocalComputerName; // The length of the name in TCHAR's including the terminating NULL.
extern DWORD gLocalComputerNameLength;
//
// RPC Verifier settings
//
extern BOOL gfAppVerifierEnabled; extern BOOL gfRPCVerifierEnabled;
// Corruption patterns:
// ZeroOut - memory is zeroed-out
// Negate - 0xff pattern is written
// BitFlip - a random bit is flipped
// IncDec - a byte is incremented or decremented
// Randomize - a random byte is written
// One of the above patterns is used at random
enum tCorruptionPattern {ZeroOut, Negate, BitFlip, IncDec, Randomize, AllPatterns=100};
// When choosing a random corruption pattern to apply, we will pick one from this range.
#define MIN_CORRUPTION_PATTERN_ID (0)
#define MAX_CORRUPTION_PATTERN_ID (4)
// Corruption can be of a fixed or random size.
enum tCorruptionSizeType {FixedSize, RandomSize};
// Corruption may be spacially localized or randomized.
// When it is localized, a sub-sequence of the buffer will be corrupted.
// When it is randomized, random elements of the buffer will be corrupted.
enum tCorruptionDistributionType {LocalizedDistribution, RandomizedDistribution};
//
// All of the RPC verifier settings are contained in a single
// structure. We will allocate and initialize it iff
// the RPC verifier is enabled.
//
typedef struct _tRpcVerifierSettings { // Fault injecting ImpersonateClient calls
BOOL fFaultInjectImpersonateClient;
// Proabilities are integers 1-10000. 10000 is p=1.
unsigned int ProbFaultInjectImpersonateClient; // Delay in seconds before the start of fault injection.
unsigned int DelayFaultInjectImpersonateClient;
// Corruption injecting the data
BOOL fCorruptionInjectServerReceives; BOOL fCorruptionInjectClientReceives;
// Proabilities of corruption are integers 1-10000. 10000 is p=1.
unsigned int ProbRpcHeaderCorruption; unsigned int ProbDataCorruption; unsigned int ProbSecureDataCorruption;
tCorruptionPattern CorruptionPattern;
tCorruptionSizeType CorruptionSizeType;
// For Fixed size - set the size of the corruption in bytes
// For Random size - set the maximum size of the corruption.
// Actual size may be between 1 and gCorruptionSize
unsigned int CorruptionSize;
tCorruptionDistributionType CorruptionDistributionType;
unsigned int ProbBufferTruncation; unsigned int MaxBufferTruncationSize;
// Fault injecting transport failures.
BOOL fFaultInjectTransports; unsigned int ProbFaultInjectTransports;
// Injecting pauses into calls to external APIs
BOOL fPauseInjectExternalAPIs; unsigned int ProbPauseInjectExternalAPIs; unsigned int PauseInjectExternalAPIsMaxWait;
// Initialized to True if the process is running under a high-priv account.
// This is used to detect if privileges are being leaked.
BOOL IsHighPrivilege;
// Optionally supressing app verifier breaks on bad RPC practictices.
BOOL fSupressAppVerifierBreaks;
// Causes RPC to switch to the allocation off a read-only paged heap.
// Each allocation off the heap is guarded by a read-only page. This
// catches AV's but still allows NDR to walk of the end of buffers a little.
BOOL fReadonlyPagedHeap;
} tRpcVerifierSettings;
extern tRpcVerifierSettings *pRpcVerifierSettings;
//
// Macros for some common conditions and states.
//
extern BOOL gfRpcVerifierCorruptionExpected;
#define gfRpcVerifierCorruptionInjectClientReceives \
( \ gfRPCVerifierEnabled && \ pRpcVerifierSettings->fCorruptionInjectClientReceives \ )
#define gfRpcVerifierCorruptionInjectServerReceives \
( \ gfRPCVerifierEnabled && \ pRpcVerifierSettings->fCorruptionInjectServerReceives \ )
#define gfRpcVerifierSupressAppVerifierBreaks (pRpcVerifierSettings->fSupressAppVerifierBreaks)
#define gfRPCVerifierEnabledWithBreaks (gfRPCVerifierEnabled && !gfRpcVerifierSupressAppVerifierBreaks)
// When defined, this macro builds a private with corruption injection for lrpc.
//#define RPC_LRPC_CORRUPTION
//
// RPC Verifier utility functions
//
// Generates a boolean with P(True)=Prob/10000.
inline BOOL RndBool( unsigned int Prob );
// The buffer types passed to the corruption injection routine.
enum tBufferType {ServerReceive, ClientReceive};
// Injects corruption into a buffer
extern void CorruptionInject( tBufferType BufferType, unsigned int *pBufferLength, void **pBuffer );
extern void PrintCurrentStackTrace( unsigned int FramesToSkip, unsigned int Size );
extern void PrintUUID( GUID *guid );
#define RPC_VERIFIER_PRINT_OFFENDING_STACK(FramesToSkip, FramesToPrint) \
DbgPrint("RPC: Offending Stack:\n"); \ PrintCurrentStackTrace(FramesToSkip, FramesToPrint); \ DbgPrint("RPC: To determine the symbolic stack, do an \"ln\" on the above addresses in the context of the faulting process.\n\n")
//
// Macros used to print app verifier warnings.
//
#define RPC_VERIFIER_UNSECURE_IF_REMOTELY_ACCESSIBLE (0x10)
#define RPC_VERIFIER_DISABLING_SELECTIVE_BINDING (0x20)
#define RPC_VERIFIER_WEAK_SECURITY_FOR_REMOTE_CALL (0x30)
#define RPC_VERIFIER_UNSAFE_PROTOCOL (0x40)
#define RPC_VERIFIER_UNSAFE_FEATURE (0x50)
#define RPC_VERIFIER_NO_LOCAL_MUTUAL_AUTHENTICATION (0x60)
#define RPC_VERIFIER_REGISTERING_NONROBUST_IF (0x70)
#define RPC_VERIFIER_ARGUMENTS_IGNORED (0x80)
#define RPC_VERIFIER_PRIVILEGE_LEAK (0x90)
#define RPC_VERIFIER_WARNING_MSG(Msg, WarningType) \
VERIFIER_STOP(APPLICATION_VERIFIER_RPC_ERROR | APPLICATION_VERIFIER_NO_BREAK, \ Msg, WarningType, "RpcWarningType", 0, NULL, 0, NULL, 0, NULL); \
//
// RPC Verifier debuging macros
//
// Macro used to assert when corruption injection is not enabled.
// This allows us to run with corruption injection on checked builds without
// triggering the asserts that catch corruption.
#if DBG
#define CORRUPTION_ASSERT(cond) \
if (!gfRpcVerifierCorruptionExpected) \ { \ ASSERT(cond); \ } #else // DBG
#define CORRUPTION_ASSERT(cond) ((void) 0)
#endif // DBG
// Set when building a private with verifier
// debugging spew.
//#define VERIFIER_DBG
#ifdef VERIFIER_DBG
#define VERIFIER_DBG_PRINT_0(s) DbgPrint(s)
#define VERIFIER_DBG_PRINT_1(s, x1) DbgPrint(s, x1)
#define VERIFIER_DBG_PRINT_2(s, x1, x2) DbgPrint(s, x1, x2)
#define VERIFIER_DBG_PRINT_3(s, x1, x2, x3) DbgPrint(s, x1, x2, x3)
#else
#define VERIFIER_DBG_PRINT_0(x) ((void) 0)
#define VERIFIER_DBG_PRINT_1(s, x1) ((void) 0)
#define VERIFIER_DBG_PRINT_2(s, x1, x2) ((void) 0)
#define VERIFIER_DBG_PRINT_3(s, x1, x2, x3) ((void) 0)
#endif
//
// Per-interface security check exemptions.
//
// The flags for various security checks that may be disabled for an interface:
// Registering an interface that is remotely acessible without a security callback
// and without RPC_IF_ALLOW_SECURE_ONLY flag.
#define ALLOW_UNSECURE_REMOTE_ACCESS 0x00000001
// An interface may be called remotely by without RPC_C_AUTHN_LEVEL_PKT_PRIVACY
#define ALLOW_UNENCRYPTED_REMOTE_ACCESS 0x00000002
// An interface may be called remotely by without mutual authentication.
#define ALLOW_NO_MUTUAL_AUTH_REMOTE_ACCESS 0x00000004
#define ALLOW_EVERYTHING 0xffffffff
// Determines whether a security check is disabled for a given interface.
extern BOOL IsInterfaceExempt ( IN GUID *IfUuid, IN DWORD CheckFlag );
//
// Detecting unsafe protseqs.
//
// Determines whether a given protseq is unsafe.
extern BOOL IsProtseqUnsafe ( IN RPC_CHAR *ProtocolSequence );
//
// Paged BCache settings
//
enum BCacheMode { BCacheModeCached, // Allocations go through the cache.
BCacheModeDirect // Allocations go directly to the heap.
};
// set to one of the constants above
extern BCacheMode gBCacheMode;
// 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;
//
// Security support functions
//
extern RPC_STATUS IsCurrentUserAdmin( void );
//
// 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_IF 'i'
#define SU_SECCRED 'S'
#define SU_HTTPv2 '2'
#define SU_CORRUPT 'O'
#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
// The RPC event log and the size of the RPC event log.
// When the RPC verifier is enabled we will re-allocate the log and extend its size.
extern struct RPC_EVENT *RpcEvents; extern long EventArrayLength;
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__ */
|