Skip to content

Commit

Permalink
fix: Read Windows Version from Registry (#623)
Browse files Browse the repository at this point in the history
We were previously relying on the `kernel32.dll` version, as does
Crashpad. However that version can lag behind OS releases, which can
manifest itself as failing integration tests, as the version does not
match the one returned from python `platform.version()`.
This tries to use `ntoskrnl.exe` as the kernel version, but falls back to
`kernel32.dll` as before in case that does not work.
  • Loading branch information
Swatinem authored Jan 18, 2022
1 parent dc1e864 commit 497636c
Showing 1 changed file with 67 additions and 14 deletions.
81 changes: 67 additions & 14 deletions src/sentry_os.c
Original file line number Diff line number Diff line change
@@ -1,9 +1,28 @@
#include "sentry_os.h"
#include "sentry_string.h"
#include "sentry_utils.h"

#ifdef SENTRY_PLATFORM_WINDOWS

# include <winver.h>
# define CURRENT_VERSION "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"

void *
sentry__try_file_version(LPCWSTR filename)
{

DWORD size = GetFileVersionInfoSizeW(filename, NULL);
if (!size) {
return NULL;
}

void *ffibuf = sentry_malloc(size);
if (!GetFileVersionInfoW(filename, 0, size, ffibuf)) {
sentry_free(ffibuf);
return NULL;
}
return ffibuf;
}

sentry_value_t
sentry__get_os_context(void)
Expand All @@ -15,15 +34,11 @@ sentry__get_os_context(void)

sentry_value_set_by_key(os, "name", sentry_value_new_string("Windows"));

void *ffibuf = NULL;

DWORD size = GetFileVersionInfoSizeW(L"kernel32.dll", NULL);
if (!size) {
goto fail;
void *ffibuf = sentry__try_file_version(L"ntoskrnl.exe");
if (!ffibuf) {
ffibuf = sentry__try_file_version(L"kernel32.dll");
}

ffibuf = sentry_malloc(size);
if (!GetFileVersionInfoW(L"kernel32.dll", 0, size, ffibuf)) {
if (!ffibuf) {
goto fail;
}

Expand All @@ -34,17 +49,55 @@ sentry__get_os_context(void)
}
ffi->dwFileFlags &= ffi->dwFileFlagsMask;

uint32_t major_version = ffi->dwFileVersionMS >> 16;
uint32_t minor_version = ffi->dwFileVersionMS & 0xffff;
uint32_t build_version = ffi->dwFileVersionLS >> 16;
uint32_t ubr = ffi->dwFileVersionLS & 0xffff;

char buf[32];
snprintf(buf, sizeof(buf), "%u.%u.%u", ffi->dwFileVersionMS >> 16,
ffi->dwFileVersionMS & 0xffff, ffi->dwFileVersionLS >> 16);
snprintf(buf, sizeof(buf), "%u.%u.%u.%lu", major_version, minor_version,
build_version, ubr);
sentry_value_set_by_key(os, "kernel_version", sentry_value_new_string(buf));

sentry_value_set_by_key(os, "version", sentry_value_new_string(buf));
sentry_free(ffibuf);

snprintf(buf, sizeof(buf), "%lu", ffi->dwFileVersionLS & 0xffff);
// The `CurrentMajorVersionNumber`, `CurrentMinorVersionNumber` and `UBR`
// are DWORD, while `CurrentBuild` is a SZ (text).

sentry_value_set_by_key(os, "build", sentry_value_new_string(buf));
uint32_t reg_version = 0;
DWORD buf_size = sizeof(uint32_t);
if (RegGetValueA(HKEY_LOCAL_MACHINE, CURRENT_VERSION,
"CurrentMajorVersionNumber", RRF_RT_REG_DWORD, NULL, &reg_version,
&buf_size)
== ERROR_SUCCESS) {
major_version = reg_version;
}
buf_size = sizeof(uint32_t);
if (RegGetValueA(HKEY_LOCAL_MACHINE, CURRENT_VERSION,
"CurrentMinorVersionNumber", RRF_RT_REG_DWORD, NULL, &reg_version,
&buf_size)
== ERROR_SUCCESS) {
minor_version = reg_version;
}
buf_size = sizeof(buf);
if (RegGetValueA(HKEY_LOCAL_MACHINE, CURRENT_VERSION, "CurrentBuild",
RRF_RT_REG_SZ, NULL, buf, &buf_size)
== ERROR_SUCCESS) {
build_version = (uint32_t)sentry__strtod_c(buf, NULL);
}
buf_size = sizeof(uint32_t);
if (RegGetValueA(HKEY_LOCAL_MACHINE, CURRENT_VERSION, "UBR",
RRF_RT_REG_DWORD, NULL, &reg_version, &buf_size)
== ERROR_SUCCESS) {
ubr = reg_version;
}

sentry_free(ffibuf);
snprintf(buf, sizeof(buf), "%u.%u.%u", major_version, minor_version,
build_version);
sentry_value_set_by_key(os, "version", sentry_value_new_string(buf));

snprintf(buf, sizeof(buf), "%lu", ubr);
sentry_value_set_by_key(os, "build", sentry_value_new_string(buf));

sentry_value_freeze(os);
return os;
Expand Down

0 comments on commit 497636c

Please sign in to comment.