Index: include/ruby/intern.h =================================================================== --- include/ruby/intern.h (revision 26984) +++ include/ruby/intern.h (working copy) @@ -838,6 +838,10 @@ void rb_frame_pop(void); int rb_frame_method_id_and_class(ID *idp, VALUE *klassp); +#ifdef _WIN32 +int w32_conv_to_utf16(volatile VALUE *strp); +#endif + #if defined(__cplusplus) #if 0 { /* satisfy cc-mode */ Index: include/ruby/win32.h =================================================================== --- include/ruby/win32.h (revision 26984) +++ include/ruby/win32.h (working copy) @@ -274,6 +274,7 @@ extern int rb_w32_isatty(int); #endif extern int rb_w32_mkdir(const char *, int); +extern int rb_w32_wmkdir(const WCHAR *, int); extern int rb_w32_rmdir(const char *); extern int rb_w32_unlink(const char *); extern int rb_w32_stati64(const char *, struct stati64 *); Index: io.c =================================================================== --- io.c (revision 26984) +++ io.c (working copy) @@ -4411,35 +4411,6 @@ #endif }; -#ifdef _WIN32 -static rb_encoding * -w32_utf16(void) -{ - static rb_encoding *utf16 = (rb_encoding *)-1; - if (utf16 == (rb_encoding *)-1) { - utf16 = rb_enc_find("UTF-16LE"); - if (utf16 == rb_ascii8bit_encoding()) - utf16 = NULL; - } - return utf16; -} - -static int -w32_conv_to_utf16(volatile VALUE *strp) -{ - rb_encoding *utf16 = w32_utf16(); - if (utf16) { - VALUE wstr = rb_str_encode(*strp, rb_enc_from_encoding(utf16), 0, Qnil); - rb_enc_str_buf_cat(wstr, "", 1, utf16); /* workaround */ - *strp = wstr; - return 1; - } - else { - return 0; - } -} -#endif - static VALUE sysopen_func(void *ptr) { Index: dir.c =================================================================== --- dir.c (revision 26984) +++ dir.c (working copy) @@ -937,6 +937,9 @@ dir_s_mkdir(int argc, VALUE *argv, VALUE obj) { VALUE path, vmode; +#ifdef _WIN32 + VALUE wpath; +#endif int mode; if (rb_scan_args(argc, argv, "11", &path, &vmode) == 2) { @@ -947,6 +950,15 @@ } check_dirname(&path); +#ifdef _WIN32 + wpath = path; + if (w32_conv_to_utf16(&wpath) != 0) { + OBJ_FREEZE(wpath); + if (rb_w32_wmkdir((WCHAR *)RSTRING_PTR(wpath), mode) == -1) + rb_sys_fail(RSTRING_PTR(path)); + } + else +#endif if (mkdir(RSTRING_PTR(path), mode) == -1) rb_sys_fail(RSTRING_PTR(path)); Index: win32/win32.c =================================================================== --- win32/win32.c (revision 26984) +++ win32/win32.c (working copy) @@ -5162,6 +5162,24 @@ } int +rb_w32_wmkdir(const WCHAR *wpath, int mode) +{ + int ret = -1; + RUBY_CRITICAL(do { + if (CreateDirectoryW(wpath, NULL) == FALSE) { + errno = map_errno(GetLastError()); + break; + } + if (_wchmod(wpath, mode) == -1) { + RemoveDirectoryW(wpath); + break; + } + ret = 0; + } while (0)); + return ret; +} + +int rb_w32_rmdir(const char *path) { int ret = 0; @@ -5291,3 +5309,31 @@ return *ip < 0; } #endif + + +static rb_encoding * +w32_utf16(void) +{ + static rb_encoding *utf16 = (rb_encoding *)-1; + if (utf16 == (rb_encoding *)-1) { + utf16 = rb_enc_find("UTF-16LE"); + if (utf16 == rb_ascii8bit_encoding()) + utf16 = NULL; + } + return utf16; +} + +int +w32_conv_to_utf16(volatile VALUE *strp) +{ + rb_encoding *utf16 = w32_utf16(); + if (utf16) { + VALUE wstr = rb_str_encode(*strp, rb_enc_from_encoding(utf16), 0, Qnil); + rb_enc_str_buf_cat(wstr, "", 1, utf16); /* workaround */ + *strp = wstr; + return 1; + } + else { + return 0; + } +}