Win32: Improve platform error messages

Related to #733.
This commit is contained in:
Camilla Löwy 2017-01-19 20:29:27 +01:00
parent c873327fe3
commit c28778e28c
7 changed files with 122 additions and 83 deletions

View File

@ -120,6 +120,7 @@ information on what to include when reporting a bug.
- Bugfix: `glfwGetInstanceProcAddress` returned `NULL` for - Bugfix: `glfwGetInstanceProcAddress` returned `NULL` for
`vkGetInstanceProcAddr` when `_GLFW_VULKAN_STATIC` was enabled `vkGetInstanceProcAddr` when `_GLFW_VULKAN_STATIC` was enabled
- Bugfix: Invalid library paths were used in test and example CMake files (#930) - 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: Undecorated windows could not be iconified by the user (#861)
- [Win32] Bugfix: Deadzone logic could underflow with some controllers (#910) - [Win32] Bugfix: Deadzone logic could underflow with some controllers (#910)
- [Win32] Bugfix: Bitness test in `FindVulkan.cmake` was VS specific (#928) - [Win32] Bugfix: Bitness test in `FindVulkan.cmake` was VS specific (#928)

View File

@ -44,9 +44,8 @@ static int getPixelFormatAttrib(_GLFWwindow* window, int pixelFormat, int attrib
pixelFormat, pixelFormat,
0, 1, &attrib, &value)) 0, 1, &attrib, &value))
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to retrieve pixel format attribute %i", "WGL: Failed to retrieve pixel format attribute");
attrib);
return 0; return 0;
} }
@ -237,8 +236,8 @@ static void makeContextCurrentWGL(_GLFWwindow* window)
_glfwPlatformSetCurrentContext(window); _glfwPlatformSetCurrentContext(window);
else else
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to make context current"); "WGL: Failed to make context current");
_glfwPlatformSetCurrentContext(NULL); _glfwPlatformSetCurrentContext(NULL);
} }
} }
@ -246,8 +245,8 @@ static void makeContextCurrentWGL(_GLFWwindow* window)
{ {
if (!wglMakeCurrent(NULL, NULL)) if (!wglMakeCurrent(NULL, NULL))
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to clear current context"); "WGL: Failed to clear current context");
} }
_glfwPlatformSetCurrentContext(NULL); _glfwPlatformSetCurrentContext(NULL);
@ -353,25 +352,24 @@ static void loadWGLExtensions(void)
if (!SetPixelFormat(dc, ChoosePixelFormat(dc, &pfd), &pfd)) if (!SetPixelFormat(dc, ChoosePixelFormat(dc, &pfd), &pfd))
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to set pixel format for dummy context"); "WGL: Failed to set pixel format for dummy context");
return; return;
} }
rc = wglCreateContext(dc); rc = wglCreateContext(dc);
if (!rc) if (!rc)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to create dummy context"); "WGL: Failed to create dummy context");
return; return;
} }
if (!wglMakeCurrent(dc, rc)) if (!wglMakeCurrent(dc, rc))
{ {
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to make dummy context current");
wglDeleteContext(rc); wglDeleteContext(rc);
_glfwInputError(GLFW_PLATFORM_ERROR,
"WGL: Failed to make dummy context current");
return; return;
} }
@ -430,7 +428,8 @@ GLFWbool _glfwInitWGL(void)
_glfw.wgl.instance = LoadLibraryA("opengl32.dll"); _glfw.wgl.instance = LoadLibraryA("opengl32.dll");
if (!_glfw.wgl.instance) 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; return GLFW_FALSE;
} }
@ -497,15 +496,15 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
if (!DescribePixelFormat(window->context.wgl.dc, if (!DescribePixelFormat(window->context.wgl.dc,
pixelFormat, sizeof(pfd), &pfd)) pixelFormat, sizeof(pfd), &pfd))
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to retrieve PFD for selected pixel format"); "WGL: Failed to retrieve PFD for selected pixel format");
return GLFW_FALSE; return GLFW_FALSE;
} }
if (!SetPixelFormat(window->context.wgl.dc, pixelFormat, &pfd)) if (!SetPixelFormat(window->context.wgl.dc, pixelFormat, &pfd))
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to set selected pixel format"); "WGL: Failed to set selected pixel format");
return GLFW_FALSE; return GLFW_FALSE;
} }
@ -669,8 +668,8 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
window->context.wgl.handle = wglCreateContext(window->context.wgl.dc); window->context.wgl.handle = wglCreateContext(window->context.wgl.dc);
if (!window->context.wgl.handle) if (!window->context.wgl.handle)
{ {
_glfwInputError(GLFW_VERSION_UNAVAILABLE, _glfwInputErrorWin32(GLFW_VERSION_UNAVAILABLE,
"WGL: Failed to create OpenGL context"); "WGL: Failed to create OpenGL context");
return GLFW_FALSE; return GLFW_FALSE;
} }
@ -678,8 +677,8 @@ GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
{ {
if (!wglShareLists(share, window->context.wgl.handle)) if (!wglShareLists(share, window->context.wgl.handle))
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to enable sharing with specified OpenGL context"); "WGL: Failed to enable sharing with specified OpenGL context");
return GLFW_FALSE; return GLFW_FALSE;
} }
} }

View File

@ -67,7 +67,7 @@ static GLFWbool loadLibraries(void)
_glfw.win32.winmm.instance = LoadLibraryA("winmm.dll"); _glfw.win32.winmm.instance = LoadLibraryA("winmm.dll");
if (!_glfw.win32.winmm.instance) 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; return GLFW_FALSE;
} }
@ -77,7 +77,7 @@ static GLFWbool loadLibraries(void)
_glfw.win32.user32.instance = LoadLibraryA("user32.dll"); _glfw.win32.user32.instance = LoadLibraryA("user32.dll");
if (!_glfw.win32.user32.instance) 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; return GLFW_FALSE;
} }
@ -315,8 +315,8 @@ static HWND createHelperWindow(void)
NULL); NULL);
if (!window) if (!window)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to create helper window"); "Win32: Failed to create helper window");
return NULL; return NULL;
} }
@ -360,12 +360,18 @@ WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source)
length = MultiByteToWideChar(CP_UTF8, 0, source, -1, NULL, 0); length = MultiByteToWideChar(CP_UTF8, 0, source, -1, NULL, 0);
if (!length) if (!length)
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to convert string from UTF-8");
return NULL; return NULL;
}
target = calloc(length, sizeof(WCHAR)); target = calloc(length, sizeof(WCHAR));
if (!MultiByteToWideChar(CP_UTF8, 0, source, -1, target, length)) if (!MultiByteToWideChar(CP_UTF8, 0, source, -1, target, length))
{ {
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to convert string from UTF-8");
free(target); free(target);
return NULL; return NULL;
} }
@ -382,12 +388,18 @@ char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source)
length = WideCharToMultiByte(CP_UTF8, 0, source, -1, NULL, 0, NULL, NULL); length = WideCharToMultiByte(CP_UTF8, 0, source, -1, NULL, 0, NULL, NULL);
if (!length) if (!length)
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to convert string to UTF-8");
return NULL; return NULL;
}
target = calloc(length, 1); target = calloc(length, 1);
if (!WideCharToMultiByte(CP_UTF8, 0, source, -1, target, length, NULL, NULL)) 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); free(target);
return NULL; return NULL;
} }
@ -395,6 +407,27 @@ char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source)
return target; 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 ////// ////// GLFW platform API //////

View File

@ -47,11 +47,7 @@ static _GLFWmonitor* createMonitor(DISPLAY_DEVICEW* adapter,
else else
name = _glfwCreateUTF8FromWideStringWin32(adapter->DeviceString); name = _glfwCreateUTF8FromWideStringWin32(adapter->DeviceString);
if (!name) if (!name)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Win32: Failed to convert string to UTF-8");
return NULL; return NULL;
}
dc = CreateDCW(L"DISPLAY", adapter->DeviceName, NULL, NULL); dc = CreateDCW(L"DISPLAY", adapter->DeviceName, NULL, NULL);
@ -213,6 +209,7 @@ GLFWbool _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desire
GLFWvidmode current; GLFWvidmode current;
const GLFWvidmode* best; const GLFWvidmode* best;
DEVMODEW dm; DEVMODEW dm;
LONG result;
best = _glfwChooseVideoMode(monitor, desired); best = _glfwChooseVideoMode(monitor, desired);
_glfwPlatformGetVideoMode(monitor, &current); _glfwPlatformGetVideoMode(monitor, &current);
@ -231,13 +228,34 @@ GLFWbool _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desire
if (dm.dmBitsPerPel < 15 || dm.dmBitsPerPel >= 24) if (dm.dmBitsPerPel < 15 || dm.dmBitsPerPel >= 24)
dm.dmBitsPerPel = 32; dm.dmBitsPerPel = 32;
if (ChangeDisplaySettingsExW(monitor->win32.adapterName, result = ChangeDisplaySettingsExW(monitor->win32.adapterName,
&dm, &dm,
NULL, NULL,
CDS_FULLSCREEN, CDS_FULLSCREEN,
NULL) != DISP_CHANGE_SUCCESSFUL) 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; return GLFW_FALSE;
} }

View File

@ -342,6 +342,7 @@ void _glfwTerminateThreadLocalStorageWin32(void);
WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source); WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source);
char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source); char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source);
void _glfwInputErrorWin32(int error, const char* description);
void _glfwInitTimerWin32(void); void _glfwInitTimerWin32(void);

View File

@ -37,8 +37,8 @@ GLFWbool _glfwInitThreadLocalStorageWin32(void)
_glfw.win32_tls.context = TlsAlloc(); _glfw.win32_tls.context = TlsAlloc();
if (_glfw.win32_tls.context == TLS_OUT_OF_INDEXES) if (_glfw.win32_tls.context == TLS_OUT_OF_INDEXES)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to allocate TLS index"); "Win32: Failed to allocate TLS index");
return GLFW_FALSE; return GLFW_FALSE;
} }

View File

@ -133,16 +133,16 @@ static HICON createIcon(const GLFWimage* image,
if (!color) if (!color)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to create RGBA bitmap"); "Win32: Failed to create RGBA bitmap");
return NULL; return NULL;
} }
mask = CreateBitmap(image->width, image->height, 1, 1, NULL); mask = CreateBitmap(image->width, image->height, 1, 1, NULL);
if (!mask) if (!mask)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to create mask bitmap"); "Win32: Failed to create mask bitmap");
DeleteObject(color); DeleteObject(color);
return NULL; return NULL;
} }
@ -172,9 +172,15 @@ static HICON createIcon(const GLFWimage* image,
if (!handle) if (!handle)
{ {
if (icon) if (icon)
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to create icon"); {
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to create icon");
}
else else
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to create cursor"); {
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to create cursor");
}
} }
return handle; return handle;
@ -906,11 +912,7 @@ static int createNativeWindow(_GLFWwindow* window,
wideTitle = _glfwCreateWideStringFromUTF8Win32(wndconfig->title); wideTitle = _glfwCreateWideStringFromUTF8Win32(wndconfig->title);
if (!wideTitle) if (!wideTitle)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Win32: Failed to convert window title to UTF-16");
return GLFW_FALSE; return GLFW_FALSE;
}
window->win32.handle = CreateWindowExW(exStyle, window->win32.handle = CreateWindowExW(exStyle,
_GLFW_WNDCLASSNAME, _GLFW_WNDCLASSNAME,
@ -927,7 +929,8 @@ static int createNativeWindow(_GLFWwindow* window,
if (!window->win32.handle) 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; return GLFW_FALSE;
} }
@ -981,8 +984,8 @@ GLFWbool _glfwRegisterWindowClassWin32(void)
if (!RegisterClassExW(&wc)) if (!RegisterClassExW(&wc))
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to register window class"); "Win32: Failed to register window class");
return GLFW_FALSE; return GLFW_FALSE;
} }
@ -1069,11 +1072,7 @@ void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
{ {
WCHAR* wideTitle = _glfwCreateWideStringFromUTF8Win32(title); WCHAR* wideTitle = _glfwCreateWideStringFromUTF8Win32(title);
if (!wideTitle) if (!wideTitle)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Win32: Failed to convert window title to UTF-16");
return; return;
}
SetWindowTextW(window->win32.handle, wideTitle); SetWindowTextW(window->win32.handle, wideTitle);
free(wideTitle); free(wideTitle);
@ -1568,8 +1567,8 @@ int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
CopyCursor(LoadCursorW(NULL, translateCursorShape(shape))); CopyCursor(LoadCursorW(NULL, translateCursorShape(shape)));
if (!cursor->win32.handle) if (!cursor->win32.handle)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to create standard cursor"); "Win32: Failed to create standard cursor");
return GLFW_FALSE; return GLFW_FALSE;
} }
@ -1596,26 +1595,22 @@ void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)
characterCount = MultiByteToWideChar(CP_UTF8, 0, string, -1, NULL, 0); characterCount = MultiByteToWideChar(CP_UTF8, 0, string, -1, NULL, 0);
if (!characterCount) if (!characterCount)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Win32: Failed to convert clipboard string to UTF-16");
return; return;
}
object = GlobalAlloc(GMEM_MOVEABLE, characterCount * sizeof(WCHAR)); object = GlobalAlloc(GMEM_MOVEABLE, characterCount * sizeof(WCHAR));
if (!object) if (!object)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to allocate global handle for clipboard"); "Win32: Failed to allocate global handle for clipboard");
return; return;
} }
buffer = GlobalLock(object); buffer = GlobalLock(object);
if (!buffer) if (!buffer)
{ {
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to lock global handle");
GlobalFree(object); GlobalFree(object);
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to lock global handle");
return; return;
} }
@ -1624,9 +1619,9 @@ void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)
if (!OpenClipboard(_glfw.win32.helperWindowHandle)) if (!OpenClipboard(_glfw.win32.helperWindowHandle))
{ {
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to open clipboard");
GlobalFree(object); GlobalFree(object);
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to open clipboard");
return; return;
} }
@ -1642,43 +1637,35 @@ const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
if (!OpenClipboard(_glfw.win32.helperWindowHandle)) 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; return NULL;
} }
object = GetClipboardData(CF_UNICODETEXT); object = GetClipboardData(CF_UNICODETEXT);
if (!object) if (!object)
{ {
_glfwInputErrorWin32(GLFW_FORMAT_UNAVAILABLE,
"Win32: Failed to convert clipboard to string");
CloseClipboard(); CloseClipboard();
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
"Win32: Failed to convert clipboard to string");
return NULL; return NULL;
} }
buffer = GlobalLock(object); buffer = GlobalLock(object);
if (!buffer) if (!buffer)
{ {
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"Win32: Failed to lock global handle");
CloseClipboard(); CloseClipboard();
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to lock global handle");
return NULL; return NULL;
} }
free(_glfw.win32.clipboardString); free(_glfw.win32.clipboardString);
_glfw.win32.clipboardString = _glfw.win32.clipboardString = _glfwCreateUTF8FromWideStringWin32(buffer);
_glfwCreateUTF8FromWideStringWin32(buffer);
GlobalUnlock(object); GlobalUnlock(object);
CloseClipboard(); CloseClipboard();
if (!_glfw.win32.clipboardString)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Win32: Failed to convert wide string to UTF-8");
return NULL;
}
return _glfw.win32.clipboardString; return _glfw.win32.clipboardString;
} }