/*++ 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 #include #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 #include #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; }