fix(wm): clear last error before calling GetWindowLongPtrW

Apparently there is a quirk of GetWindowLongPtr when querying styles. If
the style bits are genuinely 0, the API returns 0 but does not clear the
last error.

If a previous API call set an error, GetWindowLongPtr might define
"failure" as "return 0 AND GetLastError != 0".

Hence, it is important to clear the last/previous error before calling
GetWindowLongPtrW to ensure that we don't misinterpret a valid 0 return
value as an error.
This commit is contained in:
Rejdukien
2026-01-08 00:41:33 +01:00
committed by LGUG2Z
parent dcb1cd32fa
commit 10af1f3c84

View File

@@ -10,6 +10,7 @@ use std::mem::size_of;
use std::path::Path; use std::path::Path;
use windows::Win32::Foundation::COLORREF; use windows::Win32::Foundation::COLORREF;
use windows::Win32::Foundation::CloseHandle; use windows::Win32::Foundation::CloseHandle;
use windows::Win32::Foundation::GetLastError;
use windows::Win32::Foundation::HANDLE; use windows::Win32::Foundation::HANDLE;
use windows::Win32::Foundation::HINSTANCE; use windows::Win32::Foundation::HINSTANCE;
use windows::Win32::Foundation::HMODULE; use windows::Win32::Foundation::HMODULE;
@@ -17,6 +18,8 @@ use windows::Win32::Foundation::HWND;
use windows::Win32::Foundation::LPARAM; use windows::Win32::Foundation::LPARAM;
use windows::Win32::Foundation::POINT; use windows::Win32::Foundation::POINT;
use windows::Win32::Foundation::RECT; use windows::Win32::Foundation::RECT;
use windows::Win32::Foundation::SetLastError;
use windows::Win32::Foundation::WIN32_ERROR;
use windows::Win32::Foundation::WPARAM; use windows::Win32::Foundation::WPARAM;
use windows::Win32::Graphics::Dwm::DWM_CLOAKED_APP; use windows::Win32::Graphics::Dwm::DWM_CLOAKED_APP;
use windows::Win32::Graphics::Dwm::DWM_CLOAKED_INHERITED; use windows::Win32::Graphics::Dwm::DWM_CLOAKED_INHERITED;
@@ -911,18 +914,42 @@ impl WindowsApi {
fn window_long_ptr_w(hwnd: HWND, index: WINDOW_LONG_PTR_INDEX) -> eyre::Result<isize> { fn window_long_ptr_w(hwnd: HWND, index: WINDOW_LONG_PTR_INDEX) -> eyre::Result<isize> {
// Can return 0, which does not always mean that an error has occurred // Can return 0, which does not always mean that an error has occurred
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowlongptrw // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowlongptrw
Result::from(WindowsResult::from(unsafe { unsafe {
GetWindowLongPtrW(hwnd, index) SetLastError(WIN32_ERROR(0));
})) let result = GetWindowLongPtrW(hwnd, index);
if result != 0 {
Ok(result)
} else {
let last_error = GetLastError();
if last_error == WIN32_ERROR(0) {
Ok(0)
} else {
Err(std::io::Error::from_raw_os_error(last_error.0 as i32).into())
}
}
}
} }
#[cfg(target_pointer_width = "32")] #[cfg(target_pointer_width = "32")]
fn window_long_ptr_w(hwnd: HWND, index: WINDOW_LONG_PTR_INDEX) -> eyre::Result<i32> { fn window_long_ptr_w(hwnd: HWND, index: WINDOW_LONG_PTR_INDEX) -> eyre::Result<i32> {
// Can return 0, which does not always mean that an error has occurred // Can return 0, which does not always mean that an error has occurred
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowlongptrw // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowlongptrw
Result::from(WindowsResult::from(unsafe { unsafe {
GetWindowLongPtrW(hwnd, index) SetLastError(WIN32_ERROR(0));
})) let result = GetWindowLongPtrW(hwnd, index);
if result != 0 {
Ok(result)
} else {
let last_error = GetLastError();
if last_error == WIN32_ERROR(0) {
Ok(0)
} else {
Err(std::io::Error::from_raw_os_error(last_error.0 as i32).into())
}
}
}
} }
#[cfg(target_pointer_width = "64")] #[cfg(target_pointer_width = "64")]