You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1128 lines
26 KiB
1128 lines
26 KiB
//+-------------------------------------------------------------------------
|
|
//
|
|
// 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__ */
|