Commit 8cc2f2d86fa8a54b1ba87564c046e2e431e4ced0

Philip Kelley 2013-03-31T12:10:27

Win32 error reporting: Support WinHTTP errors

diff --git a/src/win32/error.c b/src/win32/error.c
index 3851ff0..4f169cf 100644
--- a/src/win32/error.c
+++ b/src/win32/error.c
@@ -8,34 +8,70 @@
 #include "common.h"
 #include "error.h"
 
+#ifdef GIT_WINHTTP
+# include <winhttp.h>
+#endif
+
+#define WC_ERR_INVALID_CHARS	0x80
+
 char *git_win32_get_error_message(DWORD error_code)
 {
 	LPWSTR lpMsgBuf = NULL;
+	HMODULE hModule = NULL;
+	char *utf8_msg = NULL;
+	int utf8_size;
+	DWORD dwFlags =
+		FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS;
 
 	if (!error_code)
 		return NULL;
 
-	if (FormatMessageW(
-				FORMAT_MESSAGE_ALLOCATE_BUFFER |
-				FORMAT_MESSAGE_FROM_SYSTEM |
-				FORMAT_MESSAGE_IGNORE_INSERTS,
-				NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
-				(LPWSTR)&lpMsgBuf, 0, NULL)) {
-		int utf8_size = WideCharToMultiByte(CP_UTF8, 0, lpMsgBuf, -1, NULL, 0, NULL, NULL);
-
-		char *lpMsgBuf_utf8 = git__malloc(utf8_size * sizeof(char));
-		if (lpMsgBuf_utf8 == NULL) {
-			LocalFree(lpMsgBuf);
-			return NULL;
+#ifdef GIT_WINHTTP
+	/* Errors raised by WinHTTP are not in the system resource table */
+	if (error_code >= WINHTTP_ERROR_BASE &&
+		error_code <= WINHTTP_ERROR_LAST)
+		hModule = GetModuleHandleW(L"winhttp");
+#endif
+
+	GIT_UNUSED(hModule);
+
+	if (hModule)
+		dwFlags |= FORMAT_MESSAGE_FROM_HMODULE;
+	else
+		dwFlags |= FORMAT_MESSAGE_FROM_SYSTEM;
+
+	if (FormatMessageW(dwFlags, hModule, error_code,
+		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+		(LPWSTR)&lpMsgBuf, 0, NULL)) {
+
+		/* Invalid code point check supported on Vista+ only */
+		if (LOBYTE(LOWORD(GetVersion())) >= 6)
+			dwFlags = WC_ERR_INVALID_CHARS;
+		else
+			dwFlags = 0;
+
+		utf8_size = WideCharToMultiByte(CP_UTF8, dwFlags,
+			lpMsgBuf, -1, NULL, 0, NULL, NULL);
+
+		if (!utf8_size) {
+			assert(0);
+			goto on_error;
 		}
-		if (!WideCharToMultiByte(CP_UTF8, 0, lpMsgBuf, -1, lpMsgBuf_utf8, utf8_size, NULL, NULL)) {
-			LocalFree(lpMsgBuf);
-			git__free(lpMsgBuf_utf8);
-			return NULL;
+
+		utf8_msg = git__malloc(utf8_size);
+
+		if (!utf8_msg)
+			goto on_error;
+
+		if (!WideCharToMultiByte(CP_UTF8, dwFlags,
+			lpMsgBuf, -1, utf8_msg, utf8_size, NULL, NULL)) {
+			git__free(utf8_msg);
+			goto on_error;
 		}
 
+on_error:
 		LocalFree(lpMsgBuf);
-		return lpMsgBuf_utf8;
 	}
-	return NULL;
+
+	return utf8_msg;
 }