diff --git a/libobs/obs-win-crash-handler.c b/libobs/obs-win-crash-handler.c index e8c16cb54..d4551b564 100644 --- a/libobs/obs-win-crash-handler.c +++ b/libobs/obs-win-crash-handler.c @@ -67,6 +67,8 @@ typedef HINSTANCE(WINAPI *SHELLEXECUTEA)(HWND hwnd, LPCTSTR operation, LPCTSTR file, LPCTSTR parameters, LPCTSTR directory, INT show_flags); +typedef HRESULT(WINAPI *GETTHREADDESCRIPTION)(HANDLE thread, PWSTR *desc); + struct stack_trace { CONTEXT context; DWORD64 instruction_ptr; @@ -391,6 +393,40 @@ static inline bool walk_stack(struct exception_handler_data *data, "Arg1 Arg2 Arg3 Address\r\n" #endif +static inline char *get_thread_name(HANDLE thread) +{ + static GETTHREADDESCRIPTION get_thread_desc = NULL; + static bool failed = false; + + if (!get_thread_desc) { + if (failed) { + return NULL; + } + + HMODULE k32 = LoadLibraryW(L"kernel32.dll"); + get_thread_desc = (GETTHREADDESCRIPTION)GetProcAddress( + k32, "GetThreadDescription"); + if (!get_thread_desc) { + failed = true; + return NULL; + } + } + + wchar_t *w_name; + HRESULT hr = get_thread_desc(thread, &w_name); + if (FAILED(hr) || !w_name) { + return NULL; + } + + struct dstr name = {0}; + dstr_from_wcs(&name, w_name); + if (name.len) + dstr_insert_ch(&name, 0, ' '); + LocalFree(w_name); + + return name.array; +} + static inline void write_thread_trace(struct exception_handler_data *data, THREADENTRY32 *entry, bool first_thread) { @@ -398,6 +434,7 @@ static inline void write_thread_trace(struct exception_handler_data *data, struct stack_trace trace = {0}; struct stack_trace *ptrace; HANDLE thread; + char *thread_name; if (first_thread != crash_thread) return; @@ -413,8 +450,13 @@ static inline void write_thread_trace(struct exception_handler_data *data, GetThreadContext(thread, &trace.context); init_instruction_data(&trace); - dstr_catf(&data->str, "\r\nThread %lX%s\r\n" TRACE_TOP, - entry->th32ThreadID, crash_thread ? " (Crashed)" : ""); + thread_name = get_thread_name(thread); + + dstr_catf(&data->str, "\r\nThread %lX:%s%s\r\n" TRACE_TOP, + entry->th32ThreadID, thread_name ? thread_name : "", + crash_thread ? " (Crashed)" : ""); + + bfree(thread_name); ptrace = crash_thread ? &data->main_trace : &trace;