diff --git a/README.md b/README.md index 7de775a5..3b9da02d 100644 --- a/README.md +++ b/README.md @@ -120,6 +120,7 @@ information on what to include when reporting a bug. - Bugfix: `glfwGetInstanceProcAddress` returned `NULL` for `vkGetInstanceProcAddr` when `_GLFW_VULKAN_STATIC` was enabled - Bugfix: Invalid library paths were used in test and example CMake files (#930) +- [Win32] Added system error strings to relevant GLFW error descriptions (#733) - [Win32] Bugfix: Undecorated windows could not be iconified by the user (#861) - [Win32] Bugfix: Deadzone logic could underflow with some controllers (#910) - [Win32] Bugfix: Bitness test in `FindVulkan.cmake` was VS specific (#928) diff --git a/src/wgl_context.c b/src/wgl_context.c index 75232466..0cbb68f5 100644 --- a/src/wgl_context.c +++ b/src/wgl_context.c @@ -44,9 +44,8 @@ static int getPixelFormatAttrib(_GLFWwindow* window, int pixelFormat, int attrib pixelFormat, 0, 1, &attrib, &value)) { - _glfwInputError(GLFW_PLATFORM_ERROR, - "WGL: Failed to retrieve pixel format attribute %i", - attrib); + _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, + "WGL: Failed to retrieve pixel format attribute"); return 0; } @@ -237,8 +236,8 @@ static void makeContextCurrentWGL(_GLFWwindow* window) _glfwPlatformSetCurrentContext(window); else { - _glfwInputError(GLFW_PLATFORM_ERROR, - "WGL: Failed to make context current"); + _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, + "WGL: Failed to make context current"); _glfwPlatformSetCurrentContext(NULL); } } @@ -246,8 +245,8 @@ static void makeContextCurrentWGL(_GLFWwindow* window) { if (!wglMakeCurrent(NULL, NULL)) { - _glfwInputError(GLFW_PLATFORM_ERROR, - "WGL: Failed to clear current context"); + _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, + "WGL: Failed to clear current context"); } _glfwPlatformSetCurrentContext(NULL); @@ -353,25 +352,24 @@ static void loadWGLExtensions(void) if (!SetPixelFormat(dc, ChoosePixelFormat(dc, &pfd), &pfd)) { - _glfwInputError(GLFW_PLATFORM_ERROR, - "WGL: Failed to set pixel format for dummy context"); + _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, + "WGL: Failed to set pixel format for dummy context"); return; } rc = wglCreateContext(dc); if (!rc) { - _glfwInputError(GLFW_PLATFORM_ERROR, - "WGL: Failed to create dummy context"); + _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, + "WGL: Failed to create dummy context"); return; } if (!wglMakeCurrent(dc, rc)) { + _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, + "WGL: Failed to make dummy context current"); wglDeleteContext(rc); - - _glfwInputError(GLFW_PLATFORM_ERROR, - "WGL: Failed to make dummy context current"); return; } @@ -430,7 +428,8 @@ GLFWbool _glfwInitWGL(void) _glfw.wgl.instance = LoadLibraryA("opengl32.dll"); if (!_glfw.wgl.instance) { - _glfwInputError(GLFW_PLATFORM_ERROR, "WGL: Failed to load opengl32.dll"); + _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, + "WGL: Failed to load opengl32.dll"); return GLFW_FALSE; } @@ -497,15 +496,15 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window, if (!DescribePixelFormat(window->context.wgl.dc, pixelFormat, sizeof(pfd), &pfd)) { - _glfwInputError(GLFW_PLATFORM_ERROR, - "WGL: Failed to retrieve PFD for selected pixel format"); + _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, + "WGL: Failed to retrieve PFD for selected pixel format"); return GLFW_FALSE; } if (!SetPixelFormat(window->context.wgl.dc, pixelFormat, &pfd)) { - _glfwInputError(GLFW_PLATFORM_ERROR, - "WGL: Failed to set selected pixel format"); + _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, + "WGL: Failed to set selected pixel format"); return GLFW_FALSE; } @@ -669,8 +668,8 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window, window->context.wgl.handle = wglCreateContext(window->context.wgl.dc); if (!window->context.wgl.handle) { - _glfwInputError(GLFW_VERSION_UNAVAILABLE, - "WGL: Failed to create OpenGL context"); + _glfwInputErrorWin32(GLFW_VERSION_UNAVAILABLE, + "WGL: Failed to create OpenGL context"); return GLFW_FALSE; } @@ -678,8 +677,8 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window, { if (!wglShareLists(share, window->context.wgl.handle)) { - _glfwInputError(GLFW_PLATFORM_ERROR, - "WGL: Failed to enable sharing with specified OpenGL context"); + _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, + "WGL: Failed to enable sharing with specified OpenGL context"); return GLFW_FALSE; } } diff --git a/src/win32_init.c b/src/win32_init.c index 6fb4caea..966433a2 100644 --- a/src/win32_init.c +++ b/src/win32_init.c @@ -67,7 +67,7 @@ static GLFWbool loadLibraries(void) _glfw.win32.winmm.instance = LoadLibraryA("winmm.dll"); if (!_glfw.win32.winmm.instance) { - _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to load winmm.dll"); + _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, "Win32: Failed to load winmm.dll"); return GLFW_FALSE; } @@ -77,7 +77,7 @@ static GLFWbool loadLibraries(void) _glfw.win32.user32.instance = LoadLibraryA("user32.dll"); if (!_glfw.win32.user32.instance) { - _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to load user32.dll"); + _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, "Win32: Failed to load user32.dll"); return GLFW_FALSE; } @@ -315,8 +315,8 @@ static HWND createHelperWindow(void) NULL); if (!window) { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Win32: Failed to create helper window"); + _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, + "Win32: Failed to create helper window"); return NULL; } @@ -360,12 +360,18 @@ WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source) length = MultiByteToWideChar(CP_UTF8, 0, source, -1, NULL, 0); if (!length) + { + _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, + "Win32: Failed to convert string from UTF-8"); return NULL; + } target = calloc(length, sizeof(WCHAR)); if (!MultiByteToWideChar(CP_UTF8, 0, source, -1, target, length)) { + _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, + "Win32: Failed to convert string from UTF-8"); free(target); return NULL; } @@ -382,12 +388,18 @@ char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source) length = WideCharToMultiByte(CP_UTF8, 0, source, -1, NULL, 0, NULL, NULL); if (!length) + { + _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, + "Win32: Failed to convert string to UTF-8"); return NULL; + } target = calloc(length, 1); if (!WideCharToMultiByte(CP_UTF8, 0, source, -1, target, length, NULL, NULL)) { + _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, + "Win32: Failed to convert string to UTF-8"); free(target); return NULL; } @@ -395,6 +407,27 @@ char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source) return target; } +// Reports the specified error, appending information about the last Win32 error +// +void _glfwInputErrorWin32(int error, const char* description) +{ + WCHAR buffer[1024] = L""; + char message[2048] = ""; + + FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS | + FORMAT_MESSAGE_MAX_WIDTH_MASK, + NULL, + GetLastError() & 0xffff, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + buffer, + sizeof(buffer), + NULL); + WideCharToMultiByte(CP_UTF8, 0, buffer, -1, message, sizeof(message), NULL, NULL); + + _glfwInputError(error, "%s: %s", description, message); +} + ////////////////////////////////////////////////////////////////////////// ////// GLFW platform API ////// diff --git a/src/win32_monitor.c b/src/win32_monitor.c index 00c39fb8..58a69d7d 100644 --- a/src/win32_monitor.c +++ b/src/win32_monitor.c @@ -47,11 +47,7 @@ static _GLFWmonitor* createMonitor(DISPLAY_DEVICEW* adapter, else name = _glfwCreateUTF8FromWideStringWin32(adapter->DeviceString); if (!name) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Win32: Failed to convert string to UTF-8"); return NULL; - } dc = CreateDCW(L"DISPLAY", adapter->DeviceName, NULL, NULL); @@ -213,6 +209,7 @@ GLFWbool _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desire GLFWvidmode current; const GLFWvidmode* best; DEVMODEW dm; + LONG result; best = _glfwChooseVideoMode(monitor, desired); _glfwPlatformGetVideoMode(monitor, ¤t); @@ -231,13 +228,34 @@ GLFWbool _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desire if (dm.dmBitsPerPel < 15 || dm.dmBitsPerPel >= 24) dm.dmBitsPerPel = 32; - if (ChangeDisplaySettingsExW(monitor->win32.adapterName, - &dm, - NULL, - CDS_FULLSCREEN, - NULL) != DISP_CHANGE_SUCCESSFUL) + result = ChangeDisplaySettingsExW(monitor->win32.adapterName, + &dm, + NULL, + CDS_FULLSCREEN, + NULL); + if (result != DISP_CHANGE_SUCCESSFUL) { - _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to set video mode"); + const char* description = "Unknown error"; + + if (result == DISP_CHANGE_BADDUALVIEW) + description = "The system uses DualView"; + else if (result == DISP_CHANGE_BADFLAGS) + description = "Invalid flags"; + else if (result == DISP_CHANGE_BADMODE) + description = "Graphics mode not supported"; + else if (result == DISP_CHANGE_BADPARAM) + description = "Invalid parameter"; + else if (result == DISP_CHANGE_FAILED) + description = "Graphics mode failed"; + else if (result == DISP_CHANGE_NOTUPDATED) + description = "Failed to write to registry"; + else if (result == DISP_CHANGE_RESTART) + description = "Computer restart required"; + + _glfwInputError(GLFW_PLATFORM_ERROR, + "Win32: Failed to set video mode: %s", + description); + return GLFW_FALSE; } diff --git a/src/win32_platform.h b/src/win32_platform.h index 511621c1..52291d5f 100644 --- a/src/win32_platform.h +++ b/src/win32_platform.h @@ -342,6 +342,7 @@ void _glfwTerminateThreadLocalStorageWin32(void); WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source); char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source); +void _glfwInputErrorWin32(int error, const char* description); void _glfwInitTimerWin32(void); diff --git a/src/win32_tls.c b/src/win32_tls.c index ef0f1d06..2bcb68a5 100644 --- a/src/win32_tls.c +++ b/src/win32_tls.c @@ -37,8 +37,8 @@ GLFWbool _glfwInitThreadLocalStorageWin32(void) _glfw.win32_tls.context = TlsAlloc(); if (_glfw.win32_tls.context == TLS_OUT_OF_INDEXES) { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Win32: Failed to allocate TLS index"); + _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, + "Win32: Failed to allocate TLS index"); return GLFW_FALSE; } diff --git a/src/win32_window.c b/src/win32_window.c index 0bc64fde..11fb6cd6 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -133,16 +133,16 @@ static HICON createIcon(const GLFWimage* image, if (!color) { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Win32: Failed to create RGBA bitmap"); + _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, + "Win32: Failed to create RGBA bitmap"); return NULL; } mask = CreateBitmap(image->width, image->height, 1, 1, NULL); if (!mask) { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Win32: Failed to create mask bitmap"); + _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, + "Win32: Failed to create mask bitmap"); DeleteObject(color); return NULL; } @@ -172,9 +172,15 @@ static HICON createIcon(const GLFWimage* image, if (!handle) { if (icon) - _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to create icon"); + { + _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, + "Win32: Failed to create icon"); + } else - _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to create cursor"); + { + _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, + "Win32: Failed to create cursor"); + } } return handle; @@ -906,11 +912,7 @@ static int createNativeWindow(_GLFWwindow* window, wideTitle = _glfwCreateWideStringFromUTF8Win32(wndconfig->title); if (!wideTitle) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Win32: Failed to convert window title to UTF-16"); return GLFW_FALSE; - } window->win32.handle = CreateWindowExW(exStyle, _GLFW_WNDCLASSNAME, @@ -927,7 +929,8 @@ static int createNativeWindow(_GLFWwindow* window, if (!window->win32.handle) { - _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to create window"); + _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, + "Win32: Failed to create window"); return GLFW_FALSE; } @@ -981,8 +984,8 @@ GLFWbool _glfwRegisterWindowClassWin32(void) if (!RegisterClassExW(&wc)) { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Win32: Failed to register window class"); + _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, + "Win32: Failed to register window class"); return GLFW_FALSE; } @@ -1069,11 +1072,7 @@ void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title) { WCHAR* wideTitle = _glfwCreateWideStringFromUTF8Win32(title); if (!wideTitle) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Win32: Failed to convert window title to UTF-16"); return; - } SetWindowTextW(window->win32.handle, wideTitle); free(wideTitle); @@ -1568,8 +1567,8 @@ int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape) CopyCursor(LoadCursorW(NULL, translateCursorShape(shape))); if (!cursor->win32.handle) { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Win32: Failed to create standard cursor"); + _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, + "Win32: Failed to create standard cursor"); return GLFW_FALSE; } @@ -1596,26 +1595,22 @@ void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string) characterCount = MultiByteToWideChar(CP_UTF8, 0, string, -1, NULL, 0); if (!characterCount) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Win32: Failed to convert clipboard string to UTF-16"); return; - } object = GlobalAlloc(GMEM_MOVEABLE, characterCount * sizeof(WCHAR)); if (!object) { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Win32: Failed to allocate global handle for clipboard"); + _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, + "Win32: Failed to allocate global handle for clipboard"); return; } buffer = GlobalLock(object); if (!buffer) { + _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, + "Win32: Failed to lock global handle"); GlobalFree(object); - - _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to lock global handle"); return; } @@ -1624,9 +1619,9 @@ void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string) if (!OpenClipboard(_glfw.win32.helperWindowHandle)) { + _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, + "Win32: Failed to open clipboard"); GlobalFree(object); - - _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to open clipboard"); return; } @@ -1642,43 +1637,35 @@ const char* _glfwPlatformGetClipboardString(_GLFWwindow* window) if (!OpenClipboard(_glfw.win32.helperWindowHandle)) { - _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to open clipboard"); + _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, + "Win32: Failed to open clipboard"); return NULL; } object = GetClipboardData(CF_UNICODETEXT); if (!object) { + _glfwInputErrorWin32(GLFW_FORMAT_UNAVAILABLE, + "Win32: Failed to convert clipboard to string"); CloseClipboard(); - - _glfwInputError(GLFW_FORMAT_UNAVAILABLE, - "Win32: Failed to convert clipboard to string"); return NULL; } buffer = GlobalLock(object); if (!buffer) { + _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, + "Win32: Failed to lock global handle"); CloseClipboard(); - - _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to lock global handle"); return NULL; } free(_glfw.win32.clipboardString); - _glfw.win32.clipboardString = - _glfwCreateUTF8FromWideStringWin32(buffer); + _glfw.win32.clipboardString = _glfwCreateUTF8FromWideStringWin32(buffer); GlobalUnlock(object); CloseClipboard(); - if (!_glfw.win32.clipboardString) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Win32: Failed to convert wide string to UTF-8"); - return NULL; - } - return _glfw.win32.clipboardString; }