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

499 lines
12 KiB
C++

/*++
Copyright (C) Microsoft Corporation, 1995 - 1999
Module Name:
util.c
Abstract:
Various helper and debug functions shared between platforms.
Author:
Mario Goertzel [MarioGo]
Revision History:
MarioGo 95/10/21 Bits 'n pieces
--*/
#include <precomp.hxx>
#include <stdarg.h>
#ifdef DEBUGRPC
BOOL ValidateError(
IN unsigned int Status,
IN unsigned int Count,
IN const int ErrorList[])
/*++
Routine Description
Tests that 'Status' is one of an expected set of error codes.
Used on debug builds as part of the VALIDATE() macro.
Example:
VALIDATE(EventStatus)
{
RPC_P_CONNECTION_CLOSED,
RPC_P_RECEIVE_FAILED,
RPC_P_CONNECTION_SHUTDOWN
// more error codes here
} END_VALIDATE;
This function is called with the RpcStatus and expected errors codes
as parameters. If RpcStatus is not one of the expected error
codes and it not zero a message will be printed to the debugger
and the function will return false. The VALIDATE macro ASSERT's the
return value.
Arguments:
Status - Status code in question.
Count - number of variable length arguments
... - One or more expected status codes. Terminated with 0 (RPC_S_OK).
Return Value:
TRUE - Status code is in the list or the status is 0.
FALSE - Status code is not in the list.
--*/
{
unsigned i;
for (i = 0; i < Count; i++)
{
if (ErrorList[i] == (int) Status)
{
return TRUE;
}
}
PrintToDebugger("RPC Assertion: unexpected failure %lu (0lx%08x)\n",
(unsigned long)Status, (unsigned long)Status);
return(FALSE);
}
#endif // DEBUGRPC
//------------------------------------------------------------------------
#ifdef RPC_ENABLE_WMI_TRACE
#include <wmistr.h>
#include <evntrace.h>
#include "wmlum.h" // private header from clustering
extern "C"
{
DWORD __stdcall
I_RpcEnableWmiTrace(
PWML_TRACE fn,
WMILIB_REG_STRUCT ** pHandle
);
}
typedef DWORD (*WMI_TRACE_FN)();
PWML_TRACE WmiTraceFn = 0;
WMILIB_REG_STRUCT WmiTraceData;
GUID WmiMessageGuid = { /* 41de81c0-aa28-460b-a455-c23809e7c170 */
0x41de81c0,
0xaa28,
0x460b,
{0xa4, 0x55, 0xc2, 0x38, 0x09, 0xe7, 0xc1, 0x70}
};
DWORD __stdcall
I_RpcEnableWmiTrace(
PWML_TRACE fn,
WMILIB_REG_STRUCT ** pHandle
)
{
WmiTraceFn = fn;
*pHandle = &WmiTraceData;
return 0;
}
#endif
BOOL fEnableLog = TRUE;
C_ASSERT(sizeof(LUID) == sizeof(__int64));
struct RPC_EVENT * RpcEvents;
long EventArrayLength = MAX_RPC_EVENT;
long NextEvent = 0;
BOOL DisableEvents = 0;
boolean SubjectExceptions[256];
boolean VerbExceptions[256];
#define LOG_VAR( x ) &(x), sizeof(x)
HANDLE hLogFile = 0;
struct RPC_EVENT_LOG
{
DWORD Thread;
union
{
struct
{
unsigned char Subject;
unsigned char Verb;
};
DWORD ZeroSet;
};
void * SubjectPointer;
void * ObjectPointer;
ULONG_PTR Data;
void * EventStackTrace[STACKTRACE_DEPTH];
};
void
TrulyLogEvent(
IN unsigned char Subject,
IN unsigned char Verb,
IN void * SubjectPointer,
IN void * ObjectPointer,
IN ULONG_PTR Data,
IN BOOL fCaptureStackTrace,
IN int AdditionalFramesToSkip
)
{
if (DisableEvents != SubjectExceptions[Subject] ||
DisableEvents != VerbExceptions[Verb])
{
return;
}
//
// Allocate the event table if it isn't already there.
//
if (!RpcEvents)
{
struct RPC_EVENT * Temp = (struct RPC_EVENT *) HeapAlloc( GetProcessHeap(),
HEAP_ZERO_MEMORY,
EventArrayLength * sizeof(RPC_EVENT) );
HANDLE LocalFile;
if (!Temp)
{
return;
}
if (InterlockedCompareExchangePointer((void **) &RpcEvents, Temp, 0) != 0)
{
HeapFree(GetProcessHeap(), 0, Temp);
}
/*
if (wcsstr(GetCommandLine(), L"fs.exe") != NULL)
{
LocalFile = CreateFile(L"d:\\rpcclnt.log", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
if (LocalFile != INVALID_HANDLE_VALUE)
{
hLogFile = LocalFile;
}
else
{
if (hLogFile == 0)
{
DbgPrint("ERROR: Could not create RPC log file: %d\n", GetLastError());
}
// else
// somebody already set it - ignore
}
}
else if (wcsstr(GetCommandLine(), L"fssvr.exe") != NULL)
{
LocalFile = CreateFile(L"d:\\rpcsvr.log", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
if (LocalFile != INVALID_HANDLE_VALUE)
{
hLogFile = LocalFile;
}
else
{
if (hLogFile == 0)
{
DbgPrint("ERROR: Could not create RPC log file: %d\n", GetLastError());
}
// else
// somebody already set it - ignore
}
}
*/
/*
DisableEvents = TRUE;
SubjectExceptions[SU_ADDRESS] = TRUE;
VerbExceptions[EV_CREATE] = TRUE;
VerbExceptions[EV_DELETE] = TRUE;
*/
/*
SubjectExceptions[SU_HEAP] = TRUE;
SubjectExceptions[SU_EVENT] = TRUE;
SubjectExceptions[SU_BCACHE] = TRUE;
*/
/*
DisableEvents = TRUE;
SubjectExceptions['a'] = TRUE;
SubjectExceptions['g'] = TRUE;
SubjectExceptions['G'] = TRUE;
SubjectExceptions['W'] = TRUE;
SubjectExceptions['X'] = TRUE;
SubjectExceptions['Y'] = TRUE;
SubjectExceptions['Z'] = TRUE;
SubjectExceptions['w'] = TRUE;
SubjectExceptions['x'] = TRUE;
SubjectExceptions['y'] = TRUE;
SubjectExceptions['z'] = TRUE;
VerbExceptions['t'] = TRUE;
VerbExceptions['G'] = TRUE;
VerbExceptions['g'] = TRUE;
VerbExceptions['w'] = TRUE;
VerbExceptions['x'] = TRUE;
VerbExceptions['y'] = TRUE;
VerbExceptions['z'] = TRUE;
VerbExceptions['W'] = TRUE;
VerbExceptions['X'] = TRUE;
VerbExceptions['Y'] = TRUE;
VerbExceptions['Z'] = TRUE;
*/
}
unsigned index = InterlockedIncrement(&NextEvent);
index %= EventArrayLength;
RpcEvents[index].Time = GetTickCount();
RpcEvents[index].Verb = Verb;
RpcEvents[index].Subject = Subject;
RpcEvents[index].Thread = (short) GetCurrentThreadId();
RpcEvents[index].SubjectPointer = SubjectPointer;
RpcEvents[index].ObjectPointer = ObjectPointer;
RpcEvents[index].Data = Data;
CallTestHook( TH_RPC_LOG_EVENT, &RpcEvents[index], 0 );
#ifdef RPC_ENABLE_WMI_TRACE
if (WmiTraceData.EnableFlags)
{
TraceMessage(
WmiTraceData.LoggerHandle,
TRACE_MESSAGE_SEQUENCE | TRACE_MESSAGE_GUID | TRACE_MESSAGE_SYSTEMINFO | TRACE_MESSAGE_TIMESTAMP,
&WmiMessageGuid,
Verb,
LOG_VAR(Subject),
LOG_VAR(SubjectPointer),
LOG_VAR(ObjectPointer),
LOG_VAR(Data),
0
);
}
#endif
#if i386
if (fCaptureStackTrace)
{
ULONG ignore;
RtlCaptureStackBackTrace(
1 + AdditionalFramesToSkip,
STACKTRACE_DEPTH,
(void **) &RpcEvents[index].EventStackTrace,
&ignore);
}
else
#endif
{
RpcEvents[index].EventStackTrace[0] = 0;
}
if (hLogFile)
{
DWORD BytesWritten;
/*
RPC_EVENT_LOG logEntry;
RPC_EVENT *CurrentEvent = &RpcEvents[index];
logEntry.Thread = CurrentEvent->Thread;
logEntry.ZeroSet = 0;
logEntry.Subject = CurrentEvent->Subject;
logEntry.Verb = CurrentEvent->Verb;
logEntry.Data = CurrentEvent->Data;
logEntry.ObjectPointer = CurrentEvent->ObjectPointer;
logEntry.SubjectPointer = CurrentEvent->SubjectPointer;
memcpy(logEntry.EventStackTrace, CurrentEvent->EventStackTrace, sizeof(logEntry.EventStackTrace));
WriteFile(hLogFile, &logEntry, sizeof(logEntry), &BytesWritten, NULL);
*/
WriteFile(hLogFile, &RpcEvents[index], sizeof(RpcEvents[index]), &BytesWritten, NULL);
}
}
void RPC_ENTRY
I_RpcLogEvent (
IN unsigned char Subject,
IN unsigned char Verb,
IN void * SubjectPointer,
IN void * ObjectPointer,
IN unsigned Data,
IN BOOL fCaptureStackTrace,
IN int AdditionalFramesToSkip
)
{
LogEvent(Subject, Verb, SubjectPointer, ObjectPointer, Data,
fCaptureStackTrace, AdditionalFramesToSkip);
}
#if 0
BOOL
IsLoggingEnabled()
{
RPC_CHAR ModulePath[ MAX_PATH ];
RPC_CHAR * ModuleName;
//
// Find out the .EXE name.
//
if (!GetModuleFileName( NULL, ModulePath, sizeof(ModulePath)))
{
return FALSE;
}
signed i;
for (i=RpcpStringLength(ModulePath)-1; i >= 0; --i)
{
if (ModulePath[i] == '\\')
{
break;
}
}
ModuleName = ModulePath + i + 1;
//
// See whether logging should be enabled.
//
HANDLE hImeo;
HANDLE hMyProcessOptions;
DWORD Error;
DWORD Value;
DWORD Length = sizeof(Value);
DWORD Type;
Error = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
RPC_CONST_STRING("Software\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options"),
0,
KEY_READ,
&hImeo
);
if (Error)
{
return FALSE;
}
Error = RegOpenKeyEx( hImeo,
ModuleName,
0,
KEY_READ,
&hMyProcessOptions
);
RegCloseKey( hImeo );
if (Error)
{
return FALSE;
}
Error = RegQueryValueEx( hMyProcessOptions,
RPC_CONST_STRING("Enable RPC Logging"),
0,
&Type,
&Value,
&Length
);
RegCloseKey( hMyProcessOptions );
if (Error)
{
return FALSE;
}
if (Type == REG_DWORD && Value)
{
return TRUE;
}
if (Type == REG_SZ && 0 == RpcpStringCompare((RPC_CHAR *) Value, RPC_CONST_CHAR('Y')))
{
return TRUE;
}
return FALSE;
}
#endif
extern "C" int __cdecl _purecall(void)
{
#ifdef DEBUGRPC
ASSERT(!"PureVirtualCalled");
#endif
return 0;
}
const RPC_CHAR *
FastGetImageBaseName (
void
)
/*++
Routine Description
Retrieves the image base name with touching minimal amount of
other memory.
Arguments:
Return Value:
A pointer to LDR private string with the image name. Don't write or
delete it!
--*/
{
PLIST_ENTRY Module;
PLDR_DATA_TABLE_ENTRY Entry;
Module = NtCurrentPeb()->Ldr->InLoadOrderModuleList.Flink;
Entry = CONTAINING_RECORD(Module,
LDR_DATA_TABLE_ENTRY,
InLoadOrderLinks);
return Entry->BaseDllName.Buffer;
}