Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -952,6 +952,8 @@ if(SENTRY_INTEGRATION_QT)
target_link_libraries(sentry PRIVATE Qt${Qt_VERSION_MAJOR}::Core)
endif()

option(SENTRY_INTEGRATION_WER "Build WER (Windows Error Reporting) integration")

include(CMakePackageConfigHelpers)
configure_package_config_file(sentry-config.cmake.in sentry-config.cmake
INSTALL_DESTINATION "${CMAKE_INSTALL_CMAKEDIR}")
Expand Down
27 changes: 17 additions & 10 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -83,16 +83,16 @@ sentry_target_sources_cwd(sentry
)

# generic platform / path / symbolizer
if(WIN32)
sentry_target_sources_cwd(sentry
sentry_random.c
sentry_random.h
sentry_windows_dbghelp.c
sentry_windows_dbghelp.h
path/sentry_path_windows.c
process/sentry_process_windows.c
symbolizer/sentry_symbolizer_windows.c
)
if(WIN32)
sentry_target_sources_cwd(sentry
sentry_random.c
sentry_random.h
sentry_windows_dbghelp.c
sentry_windows_dbghelp.h
path/sentry_path_windows.c
process/sentry_process_windows.c
symbolizer/sentry_symbolizer_windows.c
)
elseif(NX OR PROSPERO)
sentry_target_sources_cwd(sentry
sentry_unix_spinlock.h
Expand Down Expand Up @@ -306,6 +306,13 @@ if(SENTRY_INTEGRATION_QT)
integrations/sentry_integration_qt.h
)
endif()
if(SENTRY_INTEGRATION_WER AND WIN32)
target_compile_definitions(sentry PRIVATE SENTRY_INTEGRATION_WER)
sentry_target_sources_cwd(sentry
integrations/sentry_integration_wer.c
integrations/sentry_integration_wer.h
)
endif()

# screenshot
if(SENTRY_SCREENSHOT_WINDOWS)
Expand Down
193 changes: 193 additions & 0 deletions src/integrations/sentry_integration_wer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
#include "sentry_integration_wer.h"

#include "sentry_alloc.h"
#include "sentry_attachment.h"
#include "sentry_logger.h"
#include "sentry_string.h"

#include <werapi.h>

// Windows 8+ SDK
#ifndef WER_FILE_ANONYMOUS_DATA
# define WER_FILE_ANONYMOUS_DATA 0x2
#endif

// Windows 10 1703+
static HRESULT(WINAPI *g_WerRegisterCustomMetadata)(PCWSTR, PCWSTR) = NULL;
static HRESULT(WINAPI *g_WerUnregisterCustomMetadata)(PCWSTR) = NULL;

static void
wer_init(void)
{
if (g_WerRegisterCustomMetadata) {
return;
}
HMODULE kernel32 = GetModuleHandleW(L"kernel32.dll");
if (kernel32) {
g_WerRegisterCustomMetadata = (HRESULT(WINAPI *)(PCWSTR,
PCWSTR))GetProcAddress(kernel32, "WerRegisterCustomMetadata");
g_WerUnregisterCustomMetadata = (HRESULT(WINAPI *)(
PCWSTR))GetProcAddress(kernel32, "WerUnregisterCustomMetadata");
}
if (!g_WerRegisterCustomMetadata) {
SENTRY_DEBUG("WerRegisterCustomMetadata not available; "
"tag sync to WER will be skipped");
}
}

static HRESULT
wer_set_tag(void *data, const char *key, size_t key_len, const char *value,
size_t value_len)
{
(void)data;
if (!g_WerRegisterCustomMetadata) {
return S_OK;
}
if (!key || !value) {
return S_OK;
}

char *key_n = sentry__string_clone_n(key, key_len);
char *value_n = sentry__string_clone_n(value, value_len);
wchar_t *key_w = sentry__string_to_wstr(key_n);
wchar_t *value_w = sentry__string_to_wstr(value_n);
sentry_free(key_n);
sentry_free(value_n);

if (!key_w || !value_w) {
sentry_free(key_w);
sentry_free(value_w);
return E_OUTOFMEMORY;
}

HRESULT hr = g_WerRegisterCustomMetadata(key_w, value_w);
if (FAILED(hr)) {
SENTRY_WARNF(
"WerRegisterCustomMetadata failed: hr=0x%08lx", (unsigned long)hr);
}

sentry_free(value_w);
sentry_free(key_w);
return hr;
}

static HRESULT
wer_remove_tag(void *data, const char *key, size_t key_len)
{
(void)data;
if (!g_WerUnregisterCustomMetadata) {
return S_OK;
}
if (!key) {
return S_OK;
}

char *key_n = sentry__string_clone_n(key, key_len);
wchar_t *key_w = sentry__string_to_wstr(key_n);
sentry_free(key_n);

if (!key_w) {
return E_OUTOFMEMORY;
}

HRESULT hr = g_WerUnregisterCustomMetadata(key_w);
if (FAILED(hr)) {
SENTRY_WARNF("WerUnregisterCustomMetadata failed: hr=0x%08lx",
(unsigned long)hr);
}

sentry_free(key_w);
return hr;
}

static HRESULT
wer_add_attachment(void *data, sentry_attachment_t *attachment)
{
(void)data;

if (!attachment) {
return S_OK;
}

if (attachment->path) {
const wchar_t *path_w = attachment->path->path_w;
if (!path_w) {
return S_OK;
}
HRESULT hr = WerRegisterFile(
path_w, WerRegFileTypeOther, WER_FILE_ANONYMOUS_DATA);
if (FAILED(hr)) {
SENTRY_WARNF(
"WerRegisterFile failed: hr=0x%08lx", (unsigned long)hr);
}
return hr;
}

if (attachment->buf && attachment->buf_len > 0) {
if (attachment->buf_len > MAXDWORD) {
SENTRY_WARNF("WerRegisterMemoryBlock: buffer too large (%zu bytes)",
attachment->buf_len);
return E_INVALIDARG;
}
HRESULT hr = WerRegisterMemoryBlock(
(PVOID)attachment->buf, (DWORD)attachment->buf_len);
if (FAILED(hr)) {
SENTRY_WARNF(
"WerRegisterMemoryBlock failed: hr=0x%08lx", (unsigned long)hr);
}
return hr;
}

return S_OK;
}

static HRESULT
wer_remove_attachment(void *data, sentry_attachment_t *attachment)
{
(void)data;

if (!attachment) {
return S_OK;
}

if (attachment->path) {
const wchar_t *path_w = attachment->path->path_w;
if (!path_w) {
return S_OK;
}
HRESULT hr = WerUnregisterFile(path_w);
if (FAILED(hr)) {
SENTRY_WARNF(
"WerUnregisterFile failed: hr=0x%08lx", (unsigned long)hr);
}
return hr;
}

if (attachment->buf) {
HRESULT hr = WerUnregisterMemoryBlock((PVOID)attachment->buf);
if (FAILED(hr)) {
SENTRY_WARNF("WerUnregisterMemoryBlock failed: hr=0x%08lx",
(unsigned long)hr);
}
return hr;
}

return S_OK;
}

void
sentry_integration_wer_setup(sentry_scope_t *scope)
{
wer_init();

sentry_scope_observer_t *observer = sentry__scope_observer_new();
if (!observer) {
return;
}
observer->set_tag = wer_set_tag;
observer->remove_tag = wer_remove_tag;
observer->add_attachment = wer_add_attachment;
observer->remove_attachment = wer_remove_attachment;

sentry__scope_add_observer(scope, observer);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pre-init attachments skip WER

High Severity

During sentry_init, attachments from sentry_options_add_attachment are moved onto the global scope before WER setup registers its observer, and no add_attachment notifications run for that list. Those files never reach WerRegisterFile / WerRegisterMemoryBlock, so WER crash reports miss attachments that Sentry and crash backends still include.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit de2ad2d. Configure here.

15 changes: 15 additions & 0 deletions src/integrations/sentry_integration_wer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#ifndef SENTRY_INTEGRATION_WER_H_INCLUDED
#define SENTRY_INTEGRATION_WER_H_INCLUDED

#include "sentry_scope.h"

/**
* Sets up the WER integration, creating and registering a scope observer
* that syncs tags and attachments to Windows Error Reporting.
*
* Must be called while holding the scope lock (i.e., from inside
* SENTRY_WITH_SCOPE_MUT).
*/
void sentry_integration_wer_setup(sentry_scope_t *scope);

#endif
Loading
Loading