diff --git a/AK/Error.cpp b/AK/Error.cpp index 7ef941449f8..8fec89ddd62 100644 --- a/AK/Error.cpp +++ b/AK/Error.cpp @@ -1,7 +1,7 @@ /* * Copyright (c) 2023, Liav A. * Copyright (c) 2023, Cameron Youell - * Copyright (c) 2024, stasoid + * Copyright (c) 2024-2025, stasoid * * SPDX-License-Identifier: BSD-2-Clause */ @@ -11,6 +11,8 @@ # include # include # include +// Comment to prevent clang-format from including windows.h too late +# include #endif namespace AK { @@ -21,31 +23,39 @@ Error Error::from_string_view_or_print_error_and_return_errno(StringView string_ } #ifdef AK_OS_WINDOWS -Error Error::from_windows_error(DWORD code) +Error Error::from_windows_error(u64 code) { - static HashMap windows_errors; + thread_local HashMap s_windows_errors; - auto string = windows_errors.get(code); - if (string.has_value()) { + auto string = s_windows_errors.get(code); + if (string.has_value()) return Error::from_string_view(string->view()); - } else { - char* message = nullptr; - auto size = FormatMessageA( - FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - nullptr, - code, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPSTR)&message, - 0, - nullptr); - if (size == 0) - return Error::from_string_view_or_print_error_and_return_errno("Unknown error"sv, code); + char* message = nullptr; + auto size = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + nullptr, + static_cast(code), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + reinterpret_cast(&message), + 0, + nullptr); - windows_errors.set(code, { message, size }); - LocalFree(message); - return from_windows_error(code); + if (size == 0) { + static char buffer[128]; + (void)snprintf(buffer, _countof(buffer), "Error 0x%08lX while getting text of error 0x%08llX", GetLastError(), code); + return Error::from_string_view({ buffer, _countof(buffer) }); } + + auto& string_in_map = s_windows_errors.ensure(code, [message, size] { return ByteString { message, size }; }); + LocalFree(message); + return Error::from_string_view(string_in_map.view()); +} + +// This can be used both for generic Windows errors and for winsock errors because WSAGetLastError is forwarded to GetLastError. +Error Error::from_windows_error() +{ + return from_windows_error(GetLastError()); } #endif diff --git a/AK/Error.h b/AK/Error.h index fd2b704432d..71db75afa42 100644 --- a/AK/Error.h +++ b/AK/Error.h @@ -7,13 +7,8 @@ #pragma once #include -#include #include #include -#include -#ifdef AK_OS_WINDOWS -typedef unsigned long DWORD; -#endif namespace AK { @@ -29,7 +24,8 @@ public: } #ifdef AK_OS_WINDOWS - static Error from_windows_error(DWORD code); + static Error from_windows_error(u64 code); + static Error from_windows_error(); #endif // NOTE: For calling this method from within kernel code, we will simply print diff --git a/Libraries/LibCore/AnonymousBufferWindows.cpp b/Libraries/LibCore/AnonymousBufferWindows.cpp index a0089a290ec..0a0dfb58fc3 100644 --- a/Libraries/LibCore/AnonymousBufferWindows.cpp +++ b/Libraries/LibCore/AnonymousBufferWindows.cpp @@ -30,7 +30,7 @@ ErrorOr> AnonymousBufferImpl::create(size_t s { HANDLE map_handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, size >> 31 >> 1, size & 0xFFFFFFFF, NULL); if (!map_handle) - return Error::from_windows_error(GetLastError()); + return Error::from_windows_error(); return create((int)(intptr_t)map_handle, size); } @@ -39,7 +39,7 @@ ErrorOr> AnonymousBufferImpl::create(int fd, { void* ptr = MapViewOfFile((HANDLE)(intptr_t)fd, FILE_MAP_ALL_ACCESS, 0, 0, size); if (!ptr) - return Error::from_windows_error(GetLastError()); + return Error::from_windows_error(); return adopt_nonnull_ref_or_enomem(new (nothrow) AnonymousBufferImpl(fd, size, ptr)); } diff --git a/Libraries/LibCore/ProcessWindows.cpp b/Libraries/LibCore/ProcessWindows.cpp index 61219a3eeef..59cdeb80444 100644 --- a/Libraries/LibCore/ProcessWindows.cpp +++ b/Libraries/LibCore/ProcessWindows.cpp @@ -71,7 +71,7 @@ ErrorOr Process::spawn(ProcessSpawnOptions const& options) &process_info); if (!result) - return Error::from_windows_error(GetLastError()); + return Error::from_windows_error(); CloseHandle(process_info.hThread); @@ -108,7 +108,7 @@ ErrorOr Process::get_name() DWORD length = GetModuleFileNameW(NULL, path, MAX_PATH); if (!length) - return Error::from_windows_error(GetLastError()); + return Error::from_windows_error(); return String::from_utf16(Utf16View { { (u16*)path, length } }); } @@ -150,11 +150,11 @@ ErrorOr Process::wait_for_termination() { auto result = WaitForSingleObject(m_handle, INFINITE); if (result == WAIT_FAILED) - return Error::from_windows_error(GetLastError()); + return Error::from_windows_error(); DWORD exit_code = 0; if (!GetExitCodeProcess(m_handle, &exit_code)) - return Error::from_windows_error(GetLastError()); + return Error::from_windows_error(); return exit_code; } diff --git a/Libraries/LibCore/SystemWindows.cpp b/Libraries/LibCore/SystemWindows.cpp index 8fe6f69021f..ceb45498294 100644 --- a/Libraries/LibCore/SystemWindows.cpp +++ b/Libraries/LibCore/SystemWindows.cpp @@ -30,7 +30,7 @@ ErrorOr open(StringView path, int options, mode_t mode) if (::stat(sz_path, &st) == 0 && (st.st_mode & S_IFDIR)) { HANDLE dir_handle = CreateFile(sz_path, GENERIC_ALL, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); if (dir_handle == INVALID_HANDLE_VALUE) - return Error::from_windows_error(GetLastError()); + return Error::from_windows_error(); int dir_fd = _open_osfhandle((intptr_t)dir_handle, 0); if (dir_fd != -1) return dir_fd; @@ -84,7 +84,7 @@ ErrorOr ftruncate(int fd, off_t length) return result.release_error(); if (SetEndOfFile((HANDLE)_get_osfhandle(fd)) == 0) - return Error::from_windows_error(GetLastError()); + return Error::from_windows_error(); return {}; }