/*++ Copyright (c) 1999-2002 Microsoft Corporation Module Name: gen.c Abstract: Generic routines that work on all operating systems. Author: Matthew D Hendel (math) 20-Oct-1999 Revision History: --*/ #pragma once #define KBYTE (1024) #define SIGN_EXTEND(_v) ((ULONG64) (LONG64) (_v)) #define ARRAY_COUNT(_array) (sizeof (_array) / sizeof ((_array)[0])) // Ran out of memory during dump writing. #define MDSTATUS_OUT_OF_MEMORY 0x00000001 // ReadProcessMemory failed during dump writing. #define MDSTATUS_UNABLE_TO_READ_MEMORY 0x00000002 // OS routine failed during dump writing. #define MDSTATUS_CALL_FAILED 0x00000004 // Unexpected internal failure during dump writing. #define MDSTATUS_INTERNAL_ERROR 0x00000008 ULONG FORCEINLINE FileTimeToTimeDate(LPFILETIME FileTime) { ULARGE_INTEGER LargeTime; LargeTime.LowPart = FileTime->dwLowDateTime; LargeTime.HighPart = FileTime->dwHighDateTime; // Convert to seconds and from base year 1601 to base year 1970. return (ULONG)(LargeTime.QuadPart / 10000000 - 11644473600); } ULONG FORCEINLINE FileTimeToSeconds(LPFILETIME FileTime) { ULARGE_INTEGER LargeTime; LargeTime.LowPart = FileTime->dwLowDateTime; LargeTime.HighPart = FileTime->dwHighDateTime; // Convert to seconds. return (ULONG)(LargeTime.QuadPart / 10000000); } struct _INTERNAL_THREAD; struct _INTERNAL_PROCESS; struct _INTERNAL_MODULE; struct _INTERNAL_FUNCTION_TABLE; ULONG GenGetAccumulatedStatus( void ); void GenAccumulateStatus( IN ULONG Status ); void GenClearAccumulatedStatus( void ); BOOL GenExecuteIncludeThreadCallback( IN HANDLE hProcess, IN DWORD ProcessId, IN ULONG DumpType, IN ULONG ThreadId, IN MINIDUMP_CALLBACK_ROUTINE CallbackRoutine, IN PVOID CallbackParam, OUT PULONG WriteFlags ); BOOL GenExecuteIncludeModuleCallback( IN HANDLE hProcess, IN DWORD ProcessId, IN ULONG DumpType, IN ULONG64 BaseOfImage, IN MINIDUMP_CALLBACK_ROUTINE CallbackRoutine, IN PVOID CallbackParam, OUT PULONG WriteFlags ); BOOL GenGetDataContributors( IN OUT PINTERNAL_PROCESS Process, IN PINTERNAL_MODULE Module ); HANDLE GenOpenThread( DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwThreadId ); HRESULT GenAllocateThreadObject( IN struct _INTERNAL_PROCESS* Process, IN HANDLE ProcessHandle, IN ULONG ThreadId, IN ULONG DumpType, IN ULONG WriteFlags, OUT struct _INTERNAL_THREAD** Thread ); BOOL GenGetThreadInstructionWindow( IN struct _INTERNAL_PROCESS* Process, IN struct _INTERNAL_THREAD* Thread ); struct _INTERNAL_PROCESS* GenAllocateProcessObject( IN HANDLE hProcess, IN ULONG ProcessId ); BOOL GenFreeProcessObject( IN struct _INTERNAL_PROCESS * Process ); struct _INTERNAL_MODULE* GenAllocateModuleObject( IN PINTERNAL_PROCESS Process, IN PWSTR FullPath, IN ULONG_PTR BaseOfModule, IN ULONG DumpType, IN ULONG WriteFlags ); VOID GenFreeModuleObject( struct _INTERNAL_MODULE * Module ); struct _INTERNAL_UNLOADED_MODULE* GenAllocateUnloadedModuleObject( IN PWSTR Path, IN ULONG_PTR BaseOfModule, IN ULONG SizeOfModule, IN ULONG CheckSum, IN ULONG TimeDateStamp ); VOID GenFreeUnloadedModuleObject( struct _INTERNAL_UNLOADED_MODULE * Module ); struct _INTERNAL_FUNCTION_TABLE* GenAllocateFunctionTableObject( IN ULONG64 MinAddress, IN ULONG64 MaxAddress, IN ULONG64 BaseAddress, IN ULONG EntryCount, IN PDYNAMIC_FUNCTION_TABLE RawTable ); VOID GenFreeFunctionTableObject( IN struct _INTERNAL_FUNCTION_TABLE* Table ); BOOL GenIncludeUnwindInfoMemory( IN PINTERNAL_PROCESS Process, IN ULONG DumpType, IN struct _INTERNAL_FUNCTION_TABLE* Table ); LPVOID GenGetTebAddress( IN HANDLE Thread, OUT PULONG SizeOfTeb ); LPVOID GenGetPebAddress( IN HANDLE Process, OUT PULONG SizeOfPeb ); HRESULT GenGetThreadInfo( IN HANDLE Process, IN HANDLE Thread, OUT PULONG64 Teb, OUT PULONG SizeOfTeb, OUT PULONG64 StackBase, OUT PULONG64 StackLimit, OUT PULONG64 StoreBase, OUT PULONG64 StoreLimit ); PVA_RANGE GenAddMemoryBlock( IN PINTERNAL_PROCESS Process, IN MEMBLOCK_TYPE Type, IN ULONG64 Start, IN ULONG Size ); void GenRemoveMemoryRange( IN PINTERNAL_PROCESS Process, IN ULONG64 Start, IN ULONG Size ); LPVOID AllocMemory( SIZE_T Size ); VOID FreeMemory( IN LPVOID Memory ); enum { Unknown, Win9x, WinNt, WinCe }; VOID WINAPI GenGetSystemType( OUT ULONG * Type, OPTIONAL OUT ULONG * Major, OPTIONAL OUT ULONG * Minor, OPTIONAL OUT ULONG * ServicePack, OPTIONAL OUT ULONG * BuildNumber OPTIONAL ); BOOL GenGetProcessInfo( IN HANDLE hProcess, IN ULONG ProcessId, IN ULONG DumpType, IN MINIDUMP_CALLBACK_ROUTINE CallbackRoutine, IN PVOID CallbackParam, OUT struct _INTERNAL_PROCESS ** ProcessRet ); BOOL GenWriteHandleData( IN HANDLE ProcessHandle, IN HANDLE hFile, IN struct _MINIDUMP_STREAM_INFO * StreamInfo ); // // Stolen from NTRTL to avoid having to include it here. // #ifndef InitializeListHead #define InitializeListHead(ListHead) (\ (ListHead)->Flink = (ListHead)->Blink = (ListHead)) #endif // // VOID // InsertTailList( // PLIST_ENTRY ListHead, // PLIST_ENTRY Entry // ); // #ifndef InsertTailList #define InsertTailList(ListHead,Entry) {\ PLIST_ENTRY _EX_Blink;\ PLIST_ENTRY _EX_ListHead;\ _EX_ListHead = (ListHead);\ _EX_Blink = _EX_ListHead->Blink;\ (Entry)->Flink = _EX_ListHead;\ (Entry)->Blink = _EX_Blink;\ _EX_Blink->Flink = (Entry);\ _EX_ListHead->Blink = (Entry);\ } #endif // // VOID // InsertListAfter( // PLIST_ENTRY ListEntry, // PLIST_ENTRY InsertEntry // ); // #ifndef InsertListAfter #define InsertListAfter(ListEntry,InsertEntry) {\ (InsertEntry)->Flink = (ListEntry)->Flink;\ (InsertEntry)->Blink = (ListEntry);\ (ListEntry)->Flink->Blink = (InsertEntry);\ (ListEntry)->Flink = (InsertEntry);\ } #endif // // VOID // RemoveEntryList( // PLIST_ENTRY Entry // ); // #ifndef RemoveEntryList #define RemoveEntryList(Entry) {\ PLIST_ENTRY _EX_Blink;\ PLIST_ENTRY _EX_Flink;\ _EX_Flink = (Entry)->Flink;\ _EX_Blink = (Entry)->Blink;\ _EX_Blink->Flink = _EX_Flink;\ _EX_Flink->Blink = _EX_Blink;\ } #endif // // BOOLEAN // IsListEmpty( // PLIST_ENTRY ListHead // ); // #ifndef IsListEmpty #define IsListEmpty(ListHead) \ ((ListHead)->Flink == (ListHead)) #endif struct _THREADENTRY32; BOOL ProcessThread32Next( HANDLE hSnapshot, DWORD dwProcessID, struct tagTHREADENTRY32 * ThreadInfo ); BOOL ProcessThread32First( HANDLE hSnapshot, DWORD dwProcessID, struct tagTHREADENTRY32 * ThreadInfo ); ULONG CheckSum ( IN ULONG PartialSum, IN PVOID SourceVa, IN ULONG_PTR Length ); BOOL ThGetProcessInfo( IN HANDLE hProcess, IN ULONG ProcessId, IN ULONG DumpType, IN MINIDUMP_CALLBACK_ROUTINE CallbackRoutine, IN PVOID CallbackParam, OUT struct _INTERNAL_PROCESS ** ProcessRet ); // // Undefine ASSERT so we do not get RtlAssert(). // #ifdef ASSERT #undef ASSERT #endif #if DBG #define ASSERT(_x)\ if (!(_x)){\ OutputDebugString ("ASSERT Failed");\ DebugBreak ();\ } #else #define ASSERT(_x) #endif