Commit e963166019de3dca72d18bd4ee8f81519e97fdf3

Vicent Martí 2013-02-01T15:57:31

Merge pull request #1303 from csware/win32_consistent_error_encoding Win32: Make sure error messages are consistently UTF-8 encoded

diff --git a/src/common.h b/src/common.h
index 23a1e25..ca203ee 100644
--- a/src/common.h
+++ b/src/common.h
@@ -28,6 +28,7 @@
 # include <windows.h>
 # include "win32/msvc-compat.h"
 # include "win32/mingw-compat.h"
+# include "win32/error.h"
 # ifdef GIT_THREADS
 #	include "win32/pthread.h"
 #endif
diff --git a/src/errors.c b/src/errors.c
index d9827fb..3aa1757 100644
--- a/src/errors.c
+++ b/src/errors.c
@@ -51,18 +51,11 @@ void giterr_set(int error_class, const char *string, ...)
 
 	if (error_class == GITERR_OS) {
 #ifdef GIT_WIN32
-		if (win32_error_code) {
-			char *lpMsgBuf;
-
-			if (FormatMessageA(
-					FORMAT_MESSAGE_ALLOCATE_BUFFER |
-					FORMAT_MESSAGE_FROM_SYSTEM |
-					FORMAT_MESSAGE_IGNORE_INSERTS,
-					NULL, win32_error_code, 0, (LPSTR)&lpMsgBuf, 0, NULL)) {
-				git_buf_PUTS(&buf, ": ");
-				git_buf_puts(&buf, lpMsgBuf);
-				LocalFree(lpMsgBuf);
-			}
+		char * win32_error = git_win32_get_error_message(win32_error_code);
+		if (win32_error) {
+			git_buf_PUTS(&buf, ": ");
+			git_buf_puts(&buf, win32_error);
+			git__free(win32_error);
 
 			SetLastError(0);
 		}
diff --git a/src/netops.c b/src/netops.c
index 59e6bda..fd83a1c 100644
--- a/src/netops.c
+++ b/src/netops.c
@@ -40,16 +40,15 @@
 #ifdef GIT_WIN32
 static void net_set_error(const char *str)
 {
-	int size, error = WSAGetLastError();
-	LPSTR err_str = NULL;
+	int error = WSAGetLastError();
+	char * win32_error = git_win32_get_error_message(error);
 
-	size = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
-			     0, error, 0, (LPSTR)&err_str, 0, 0);
-
-	GIT_UNUSED(size);
-
-	giterr_set(GITERR_NET, "%s: %s", str, err_str);
-	LocalFree(err_str);
+	if (win32_error) {
+		giterr_set(GITERR_NET, "%s: %s", str, win32_error);
+		git__free(win32_error);
+	} else {
+		giterr_set(GITERR_NET, str);
+	}
 }
 #else
 static void net_set_error(const char *str)
diff --git a/src/win32/error.c b/src/win32/error.c
new file mode 100644
index 0000000..3851ff0
--- /dev/null
+++ b/src/win32/error.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+
+#include "common.h"
+#include "error.h"
+
+char *git_win32_get_error_message(DWORD error_code)
+{
+	LPWSTR lpMsgBuf = NULL;
+
+	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;
+		}
+		if (!WideCharToMultiByte(CP_UTF8, 0, lpMsgBuf, -1, lpMsgBuf_utf8, utf8_size, NULL, NULL)) {
+			LocalFree(lpMsgBuf);
+			git__free(lpMsgBuf_utf8);
+			return NULL;
+		}
+
+		LocalFree(lpMsgBuf);
+		return lpMsgBuf_utf8;
+	}
+	return NULL;
+}
diff --git a/src/win32/error.h b/src/win32/error.h
new file mode 100644
index 0000000..12947a2
--- /dev/null
+++ b/src/win32/error.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright (C) the libgit2 contributors. All rights reserved.
+ *
+ * This file is part of libgit2, distributed under the GNU GPL v2 with
+ * a Linking Exception. For full terms see the included COPYING file.
+ */
+
+#ifndef INCLUDE_git_win32_error_h__
+#define INCLUDE_git_win32_error_h__
+
+extern char *git_win32_get_error_message(DWORD error_code);
+
+#endif