499 lines
12 KiB
C++
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;
|
||
|
}
|
||
|
|