diff --git a/windows/debug.c b/windows/debug.c deleted file mode 100644 index bc84b639..00000000 --- a/windows/debug.c +++ /dev/null @@ -1,111 +0,0 @@ -// 25 february 2015 -#include "uipriv_windows.h" - -// uncomment the following line to enable debug messages -#define tableDebug -// uncomment the following line to halt on a debug message -#define tableDebugStop - -#ifdef tableDebug - -#include - -HRESULT logLastError(const char *context) -{ - DWORD le; - WCHAR *msg; - BOOL parenthesize = FALSE; - BOOL localFreeFailed = FALSE; - DWORD localFreeLastError; - - le = GetLastError(); - fprintf(stderr, "%s: ", context); - if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, le, 0, (LPWSTR) (&msg), 0, NULL) != 0) { - fprintf(stderr, "%S (", msg); - if (LocalFree(msg) != NULL) { - localFreeFailed = TRUE; - localFreeLastError = GetLastError(); - } - parenthesize = TRUE; - } - fprintf(stderr, "GetLastError() == %I32u", le); - if (parenthesize) - fprintf(stderr, ")"); - if (localFreeFailed) - fprintf(stderr, "; local free of system message failed with last error %I32u", localFreeLastError); - fprintf(stderr, "\n"); -#ifdef tableDebugStop - DebugBreak(); -#endif - SetLastError(le); - // a function does not have to set a last error - // if the last error we get is actually 0, then HRESULT_FROM_WIN32(0) will return S_OK (0 cast to an HRESULT, since 0 <= 0), which we don't want - // prevent this by returning E_FAIL, so the rest of the Table code doesn't barge onward - if (le == 0) - return E_FAIL; - return HRESULT_FROM_WIN32(le); -} - -HRESULT logHRESULT(const char *context, HRESULT hr) -{ - WCHAR *msg; - BOOL parenthesize = FALSE; - BOOL localFreeFailed = FALSE; - DWORD localFreeLastError; - - fprintf(stderr, "%s: ", context); - // this isn't technically documented, but everyone does it, including Microsoft (see the implementation of _com_error::ErrorMessage() in a copy of comdef.h that comes with the Windows DDK) - if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, (DWORD) hr, 0, (LPWSTR) (&msg), 0, NULL) != 0) { - fprintf(stderr, "%S (", msg); - if (LocalFree(msg) != NULL) { - localFreeFailed = TRUE; - localFreeLastError = GetLastError(); - } - parenthesize = TRUE; - } - fprintf(stderr, "HRESULT == 0x%I32X", hr); - if (parenthesize) - fprintf(stderr, ")"); - if (localFreeFailed) - fprintf(stderr, "; local free of system message failed with last error %I32u", localFreeLastError); - fprintf(stderr, "\n"); -#ifdef tableDebugStop - DebugBreak(); -#endif - return hr; -} - -HRESULT logMemoryExhausted(const char *reason) -{ - fprintf(stderr, "memory exhausted %s\n", reason); -#ifdef tableDebugStop - DebugBreak(); -#endif - return E_OUTOFMEMORY; -} - -#else - -HRESULT logLastError(const char *reason) -{ - DWORD le; - - le = GetLastError(); - // we shouldn't need to do this, but let's do this anyway just to be safe - SetLastError(le); - if (le == 0) - return E_FAIL; - return HRESULT_FROM_WIN32(le); -} - -HRESULT logHRESULT(const char *reason, HRESULT hr) -{ - return hr; -} - -HRESULT logMemoryExhausted(const char *reason) -{ - return E_OUTOFMEMORY; -} - -#endif diff --git a/windows/debug.cpp b/windows/debug.cpp new file mode 100644 index 00000000..7c025152 --- /dev/null +++ b/windows/debug.cpp @@ -0,0 +1,123 @@ +// 25 february 2015 +#include "uipriv_windows.h" + +// TODO disable logging and stopping on no-debug builds + +// TODO are the newlines needed? +static void printDebug(WCHAR *msg) +{ + OutputDebugStringW(msg); +} + +#define debugfmt L"%s:" L ## PRIiMAX L":%s()" + +HRESULT _logLastError(debugargs, const WCHAR *func, const WCHAR *s) +{ + DWORD le; + WCHAR *msg; + WCHAR *formatted; + BOOL useFormatted; + + le = GetLastError(); + + useFormatted = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, le, 0, (LPWSTR) (&formatted), 0, NULL) != 0; + if (!useFormatted) + formatted = L"\n"; + msg = debugstrf(L"[libui] " debugfmt L" %s: GetLastError() == %I32u %s", + file, line, func, + s, le, formatted); + if (useFormatted) + LocalFree(formatted); // ignore error + if (msg == NULL) { + printDebug(L"[libui] (debugstrf() failed; printing raw) "); + printDebug(file); + printDebug(func); + printDebug(s); + printDebug(L"\n"); + } else { + printDebug(msg); + uiFree(msg); + } + DebugBreak(); + + SetLastError(le); + // a function does not have to set a last error + // if the last error we get is actually 0, then HRESULT_FROM_WIN32(0) will return S_OK (0 cast to an HRESULT, since 0 <= 0), which we don't want + // prevent this by returning E_FAIL + if (le == 0) + return E_FAIL; + return HRESULT_FROM_WIN32(le); +} + +HRESULT _logHRESULT(debugargs, const WCHAR *s, HRESULT hr) +{ + DWORD le; + WCHAR *msg; + WCHAR *formatted; + BOOL useFormatted; + + useFormatted = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, hr, 0, (LPWSTR) (&formatted), 0, NULL) != 0; + if (!useFormatted) + formatted = L"\n"; + msg = debugstrf(L"[libui] " debugfmt L" %s: HRESULT == 0x%08I32X %s", + file, line, func, + s, hr, formatted); + if (useFormatted) + LocalFree(formatted); // ignore error + if (msg == NULL) { + printDebug(L"[libui] (debugstrf() failed; printing raw) "); + printDebug(file); + printDebug(func); + printDebug(s); + printDebug(L"\n"); + } else { + printDebug(msg); + uiFree(msg); + } + DebugBreak(); + + return hr; +} + +#define implbugmsg L"either you have or libui has a bug in a control implementation; if libui does, contact andlabs" + +void _implbug(debugargs, const WCHAR *format, ...) +{ + va_list ap; + WCHAR *formatted; + WCHAR *full; + const WCHAR *onerr; + + va_start(ap, format); + formatted = debugvstrf(format, ap); + va_end(ap); + if (formatted == NULL) { + onerr = s; + goto bad; + } + + full = debugstrf(L"[libui] " debugfmt L" " implbugmsg L" — %s\n", + file, line, func, + formatted); + if (full == NULL) { + onerr = formatted; + goto bad; + } + + printDebug(full); + uiFree(full); + uiFree(formatted); + goto after; + +bad: + printDebug(L"[libui] (debugstrf() failed; printing raw) "); + printDebug(implbugmsg); + printDebug(file); + printDebug(func); + printDebug(onerr); + printDebug(L"\n"); + +after: + DebugBreak(); + abort(); +} diff --git a/windows/winapi.hpp b/windows/winapi.hpp index d8277aea..434144a1 100644 --- a/windows/winapi.hpp +++ b/windows/winapi.hpp @@ -41,6 +41,7 @@ #include #include #include +#include #include #include