From b5e80f7dcd0a67db6e583275390945d089f5df38 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?D=C4=81vis=20Mos=C4=81ns?= <davispuh@gmail.com>
Date: Wed, 3 Aug 2016 20:08:54 +0300
Subject: [PATCH] Use wide WinAPI for rb_w32_getcwd

---
 win32/win32.c | 72 ++++++++++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 54 insertions(+), 18 deletions(-)

diff --git a/win32/win32.c b/win32/win32.c
index 8fd0083..38ad089 100644
--- a/win32/win32.c
+++ b/win32/win32.c
@@ -4590,37 +4590,73 @@ char *
 rb_w32_getcwd(char *buffer, int size)
 {
     char *p = buffer;
-    int len;
+    WCHAR *wbuffer;
+    int len, r;
+    VALUE rp;
 
-    len = GetCurrentDirectory(0, NULL);
+    len = GetCurrentDirectoryW(0, NULL);
     if (!len) {
 	errno = map_errno(GetLastError());
 	return NULL;
     }
 
-    if (p) {
-	if (size < len) {
-	    errno = ERANGE;
-	    return NULL;
-	}
+    if (buffer && size < len) {
+        errno = ERANGE;
+        return NULL;
     }
-    else {
-	p = malloc(len);
-	size = len;
-	if (!p) {
-	    errno = ENOMEM;
-	    return NULL;
-	}
+
+    wbuffer = malloc(len * sizeof(WCHAR));
+    if (!wbuffer) {
+        errno = ENOMEM;
+        return NULL;
     }
 
-    if (!GetCurrentDirectory(size, p)) {
+    if (!GetCurrentDirectoryW(len, wbuffer)) {
 	errno = map_errno(GetLastError());
-	if (!buffer)
-	    free(p);
+        free(wbuffer);
+        return NULL;
+    }
+
+    if (!p) {
+        size = WideCharToMultiByte(CP_UTF8, 0, wbuffer, -1, NULL, 0, NULL, NULL);
+        p = malloc(size);
+        if (!p) {
+            errno = ENOMEM;
+            return NULL;
+        }
+    }
+
+    r = WideCharToMultiByte(CP_UTF8, 0, wbuffer, -1, p, size, NULL, NULL);
+
+    free(wbuffer);
+
+    if (r == 0) {
+        DWORD lastError = GetLastError();
+        if (!buffer) {
+            free(p);
+        }
+        if (lastError == ERROR_INSUFFICIENT_BUFFER) {
+            errno = ERANGE;
+            return NULL;
+        }
+        errno = map_errno(lastError);
         return NULL;
     }
 
-    translate_char(p, '\\', '/', filecp());
+    translate_char(p, '\\', '/', CP_UTF8);
+
+    rp = rb_str_conv_enc_opts(rb_utf8_str_new_cstr(p), NULL, rb_filesystem_encoding(), ECONV_UNDEF_REPLACE, Qnil);
+    if (!buffer) {
+      free(p);
+      p = strdup(RSTRING_PTR(rp));
+    } else {
+      if (RSTRING_LEN(rp) >= size) {
+        errno = ERANGE;
+        return NULL;
+      }
+      strncpy(p, RSTRING_PTR(rp), size - 1);
+      p[size - 1] = '\0';
+    }
 
     return p;
 }
-- 
2.9.2

