authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-06-16 18:26:02-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-06-16 18:26:02-04:00
log593db7e8d0a5ad3cc1693944503f718ee96bda38
tree69c8ed14ace2b8f30031eb9040c9ac9e1d9f6079
parent04c3fae720b57e72dedbaf28982e7e9bfed47db6
parent2c8a3aaf855475cabef4e8275581a12b06417a02
signature Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #5608 from alexnask/windows_utf16_dir

Use PathSpace and wide FS calls on windows in stage1

3 files changed, 222 insertions(+), 30 deletions(-)

src/os.cpp+213-29
...@@ -6,8 +6,13 @@...@@ -6,8 +6,13 @@
6 */6 */
77
8#include "os.hpp"8#include "os.hpp"
9#include "buffer.hpp"
10#include "heap.hpp"
9#include "util.hpp"11#include "util.hpp"
10#include "error.hpp"12#include "error.hpp"
13#include "util_base.hpp"
14#include <stdint.h>
15#include <stdio.h>
1116
12#if defined(_WIN32)17#if defined(_WIN32)
1318
...@@ -73,6 +78,8 @@ typedef SSIZE_T ssize_t;...@@ -73,6 +78,8 @@ typedef SSIZE_T ssize_t;
73#endif78#endif
7479
75#if defined(ZIG_OS_WINDOWS)80#if defined(ZIG_OS_WINDOWS)
81static void utf16le_ptr_to_utf8(Buf *out, WCHAR *utf16le);
82static size_t utf8_to_utf16le(WCHAR *utf16_le, Slice<uint8_t> utf8);
76static uint64_t windows_perf_freq;83static uint64_t windows_perf_freq;
77#elif defined(__MACH__)84#elif defined(__MACH__)
78static clock_serv_t macos_calendar_clock;85static clock_serv_t macos_calendar_clock;
...@@ -148,15 +155,21 @@ static void os_spawn_process_windows(ZigList<const char *> &args, Termination *t...@@ -148,15 +155,21 @@ static void os_spawn_process_windows(ZigList<const char *> &args, Termination *t
148 os_windows_create_command_line(&command_line, args);155 os_windows_create_command_line(&command_line, args);
149156
150 PROCESS_INFORMATION piProcInfo = {0};157 PROCESS_INFORMATION piProcInfo = {0};
151 STARTUPINFO siStartInfo = {0};158 STARTUPINFOW siStartInfo = {0};
152 siStartInfo.cb = sizeof(STARTUPINFO);159 siStartInfo.cb = sizeof(STARTUPINFOW);
153160
154 const char *exe = args.at(0);161 Slice<uint8_t> exe_slice = str(args.at(0));
155 BOOL success = CreateProcessA(exe, buf_ptr(&command_line), nullptr, nullptr, TRUE, 0, nullptr, nullptr,162 auto exe_utf16_slice = Slice<WCHAR>::alloc(exe_slice.len + 1);
163 exe_utf16_slice.ptr[utf8_to_utf16le(exe_utf16_slice.ptr, exe_slice)] = 0;
164
165 auto command_line_utf16 = Slice<WCHAR>::alloc(buf_len(&command_line) + 1);
166 command_line_utf16.ptr[utf8_to_utf16le(command_line_utf16.ptr, buf_to_slice(&command_line))] = 0;
167
168 BOOL success = CreateProcessW(exe_utf16_slice.ptr, command_line_utf16.ptr, nullptr, nullptr, TRUE, CREATE_UNICODE_ENVIRONMENT, nullptr, nullptr,
156 &siStartInfo, &piProcInfo);169 &siStartInfo, &piProcInfo);
157170
158 if (!success) {171 if (!success) {
159 zig_panic("CreateProcess failed. exe: %s command_line: %s", exe, buf_ptr(&command_line));172 zig_panic("CreateProcess failed. exe: %s command_line: %s", args.at(0), buf_ptr(&command_line));
160 }173 }
161174
162 WaitForSingleObject(piProcInfo.hProcess, INFINITE);175 WaitForSingleObject(piProcInfo.hProcess, INFINITE);
...@@ -269,11 +282,13 @@ void os_path_join(Buf *dirname, Buf *basename, Buf *out_full_path) {...@@ -269,11 +282,13 @@ void os_path_join(Buf *dirname, Buf *basename, Buf *out_full_path) {
269282
270Error os_path_real(Buf *rel_path, Buf *out_abs_path) {283Error os_path_real(Buf *rel_path, Buf *out_abs_path) {
271#if defined(ZIG_OS_WINDOWS)284#if defined(ZIG_OS_WINDOWS)
272 buf_resize(out_abs_path, 4096);285 PathSpace rel_path_space = slice_to_prefixed_file_w(buf_to_slice(rel_path));
273 if (_fullpath(buf_ptr(out_abs_path), buf_ptr(rel_path), buf_len(out_abs_path)) == nullptr) {286 PathSpace out_abs_path_space;
274 zig_panic("_fullpath failed");287
288 if (_wfullpath(&out_abs_path_space.data.items[0], &rel_path_space.data.items[0], PATH_MAX_WIDE) == nullptr) {
289 zig_panic("_wfullpath failed");
275 }290 }
276 buf_resize(out_abs_path, strlen(buf_ptr(out_abs_path)));291 utf16le_ptr_to_utf8(out_abs_path, &out_abs_path_space.data.items[0]);
277 return ErrorNone;292 return ErrorNone;
278#elif defined(ZIG_OS_POSIX)293#elif defined(ZIG_OS_POSIX)
279 buf_resize(out_abs_path, PATH_MAX + 1);294 buf_resize(out_abs_path, PATH_MAX + 1);
...@@ -773,7 +788,8 @@ Error os_fetch_file(FILE *f, Buf *out_buf) {...@@ -773,7 +788,8 @@ Error os_fetch_file(FILE *f, Buf *out_buf) {
773788
774Error os_file_exists(Buf *full_path, bool *result) {789Error os_file_exists(Buf *full_path, bool *result) {
775#if defined(ZIG_OS_WINDOWS)790#if defined(ZIG_OS_WINDOWS)
776 *result = GetFileAttributes(buf_ptr(full_path)) != INVALID_FILE_ATTRIBUTES;791 PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(full_path));
792 *result = GetFileAttributesW(&path_space.data.items[0]) != INVALID_FILE_ATTRIBUTES;
777 return ErrorNone;793 return ErrorNone;
778#else794#else
779 *result = access(buf_ptr(full_path), F_OK) != -1;795 *result = access(buf_ptr(full_path), F_OK) != -1;
...@@ -1021,7 +1037,12 @@ Error os_exec_process(ZigList<const char *> &args,...@@ -1021,7 +1037,12 @@ Error os_exec_process(ZigList<const char *> &args,
1021}1037}
10221038
1023Error os_write_file(Buf *full_path, Buf *contents) {1039Error os_write_file(Buf *full_path, Buf *contents) {
1040#if defined(ZIG_OS_WINDOWS)
1041 PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(full_path));
1042 FILE *f = _wfopen(&path_space.data.items[0], L"wb");
1043#else
1024 FILE *f = fopen(buf_ptr(full_path), "wb");1044 FILE *f = fopen(buf_ptr(full_path), "wb");
1045#endif
1025 if (!f) {1046 if (!f) {
1026 zig_panic("os_write_file failed for %s", buf_ptr(full_path));1047 zig_panic("os_write_file failed for %s", buf_ptr(full_path));
1027 }1048 }
...@@ -1056,7 +1077,12 @@ static Error copy_open_files(FILE *src_f, FILE *dest_f) {...@@ -1056,7 +1077,12 @@ static Error copy_open_files(FILE *src_f, FILE *dest_f) {
1056Error os_dump_file(Buf *src_path, FILE *dest_file) {1077Error os_dump_file(Buf *src_path, FILE *dest_file) {
1057 Error err;1078 Error err;
10581079
1080#if defined(ZIG_OS_WINDOWS)
1081 PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(src_path));
1082 FILE *src_f = _wfopen(&path_space.data.items[0], L"rb");
1083#else
1059 FILE *src_f = fopen(buf_ptr(src_path), "rb");1084 FILE *src_f = fopen(buf_ptr(src_path), "rb");
1085#endif
1060 if (!src_f) {1086 if (!src_f) {
1061 int err = errno;1087 int err = errno;
1062 if (err == ENOENT) {1088 if (err == ENOENT) {
...@@ -1173,7 +1199,12 @@ Error os_update_file(Buf *src_path, Buf *dst_path) {...@@ -1173,7 +1199,12 @@ Error os_update_file(Buf *src_path, Buf *dst_path) {
1173}1199}
11741200
1175Error os_copy_file(Buf *src_path, Buf *dest_path) {1201Error os_copy_file(Buf *src_path, Buf *dest_path) {
1202#if defined(ZIG_OS_WINDOWS)
1203 PathSpace src_path_space = slice_to_prefixed_file_w(buf_to_slice(src_path));
1204 FILE *src_f = _wfopen(&src_path_space.data.items[0], L"rb");
1205#else
1176 FILE *src_f = fopen(buf_ptr(src_path), "rb");1206 FILE *src_f = fopen(buf_ptr(src_path), "rb");
1207#endif
1177 if (!src_f) {1208 if (!src_f) {
1178 int err = errno;1209 int err = errno;
1179 if (err == ENOENT) {1210 if (err == ENOENT) {
...@@ -1184,7 +1215,12 @@ Error os_copy_file(Buf *src_path, Buf *dest_path) {...@@ -1184,7 +1215,12 @@ Error os_copy_file(Buf *src_path, Buf *dest_path) {
1184 return ErrorFileSystem;1215 return ErrorFileSystem;
1185 }1216 }
1186 }1217 }
1218#if defined(ZIG_OS_WINDOWS)
1219 PathSpace dest_path_space = slice_to_prefixed_file_w(buf_to_slice(dest_path));
1220 FILE *dest_f = _wfopen(&dest_path_space.data.items[0], L"wb");
1221#else
1187 FILE *dest_f = fopen(buf_ptr(dest_path), "wb");1222 FILE *dest_f = fopen(buf_ptr(dest_path), "wb");
1223#endif
1188 if (!dest_f) {1224 if (!dest_f) {
1189 int err = errno;1225 int err = errno;
1190 if (err == ENOENT) {1226 if (err == ENOENT) {
...@@ -1205,7 +1241,12 @@ Error os_copy_file(Buf *src_path, Buf *dest_path) {...@@ -1205,7 +1241,12 @@ Error os_copy_file(Buf *src_path, Buf *dest_path) {
1205}1241}
12061242
1207Error os_fetch_file_path(Buf *full_path, Buf *out_contents) {1243Error os_fetch_file_path(Buf *full_path, Buf *out_contents) {
1244#if defined(ZIG_OS_WINDOWS)
1245 PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(full_path));
1246 FILE *f = _wfopen(&path_space.data.items[0], L"rb");
1247#else
1208 FILE *f = fopen(buf_ptr(full_path), "rb");1248 FILE *f = fopen(buf_ptr(full_path), "rb");
1249#endif
1209 if (!f) {1250 if (!f) {
1210 switch (errno) {1251 switch (errno) {
1211 case EACCES:1252 case EACCES:
...@@ -1230,11 +1271,11 @@ Error os_fetch_file_path(Buf *full_path, Buf *out_contents) {...@@ -1230,11 +1271,11 @@ Error os_fetch_file_path(Buf *full_path, Buf *out_contents) {
12301271
1231Error os_get_cwd(Buf *out_cwd) {1272Error os_get_cwd(Buf *out_cwd) {
1232#if defined(ZIG_OS_WINDOWS)1273#if defined(ZIG_OS_WINDOWS)
1233 char buf[4096];1274 PathSpace path_space;
1234 if (GetCurrentDirectory(4096, buf) == 0) {1275 if (GetCurrentDirectoryW(PATH_MAX_WIDE, &path_space.data.items[0]) == 0) {
1235 zig_panic("GetCurrentDirectory failed");1276 zig_panic("GetCurrentDirectory failed");
1236 }1277 }
1237 buf_init_from_str(out_cwd, buf);1278 utf16le_ptr_to_utf8(out_cwd, &path_space.data.items[0]);
1238 return ErrorNone;1279 return ErrorNone;
1239#elif defined(ZIG_OS_POSIX)1280#elif defined(ZIG_OS_POSIX)
1240 char buf[PATH_MAX];1281 char buf[PATH_MAX];
...@@ -1330,7 +1371,9 @@ Error os_rename(Buf *src_path, Buf *dest_path) {...@@ -1330,7 +1371,9 @@ Error os_rename(Buf *src_path, Buf *dest_path) {
1330 return ErrorNone;1371 return ErrorNone;
1331 }1372 }
1332#if defined(ZIG_OS_WINDOWS)1373#if defined(ZIG_OS_WINDOWS)
1333 if (!MoveFileExA(buf_ptr(src_path), buf_ptr(dest_path), MOVEFILE_REPLACE_EXISTING)) {1374 PathSpace src_path_space = slice_to_prefixed_file_w(buf_to_slice(src_path));
1375 PathSpace dest_path_space = slice_to_prefixed_file_w(buf_to_slice(dest_path));
1376 if (!MoveFileExW(&src_path_space.data.items[0], &dest_path_space.data.items[0], MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH)) {
1334 return ErrorFileSystem;1377 return ErrorFileSystem;
1335 }1378 }
1336#else1379#else
...@@ -1426,7 +1469,15 @@ Error os_make_path(Buf *path) {...@@ -1426,7 +1469,15 @@ Error os_make_path(Buf *path) {
14261469
1427Error os_make_dir(Buf *path) {1470Error os_make_dir(Buf *path) {
1428#if defined(ZIG_OS_WINDOWS)1471#if defined(ZIG_OS_WINDOWS)
1429 if (!CreateDirectory(buf_ptr(path), NULL)) {1472 PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(path));
1473 if (memEql(buf_to_slice(path), str("C:\\dev\\tést"))) {
1474 for (size_t i = 0; i < path_space.len; i++) {
1475 fprintf(stderr, "%d ", path_space.data.items[i]);
1476 }
1477 fprintf(stderr, "\n");
1478 }
1479
1480 if (!CreateDirectoryW(&path_space.data.items[0], NULL)) {
1430 if (GetLastError() == ERROR_ALREADY_EXISTS)1481 if (GetLastError() == ERROR_ALREADY_EXISTS)
1431 return ErrorPathAlreadyExists;1482 return ErrorPathAlreadyExists;
1432 if (GetLastError() == ERROR_PATH_NOT_FOUND)1483 if (GetLastError() == ERROR_PATH_NOT_FOUND)
...@@ -1531,18 +1582,13 @@ int os_init(void) {...@@ -1531,18 +1582,13 @@ int os_init(void) {
15311582
1532Error os_self_exe_path(Buf *out_path) {1583Error os_self_exe_path(Buf *out_path) {
1533#if defined(ZIG_OS_WINDOWS)1584#if defined(ZIG_OS_WINDOWS)
1534 buf_resize(out_path, 256);1585 PathSpace path_space;
1535 for (;;) {1586 DWORD copied_amt = GetModuleFileNameW(nullptr, &path_space.data.items[0], PATH_MAX_WIDE);
1536 DWORD copied_amt = GetModuleFileName(nullptr, buf_ptr(out_path), buf_len(out_path));1587 if (copied_amt <= 0) {
1537 if (copied_amt <= 0) {1588 return ErrorFileNotFound;
1538 return ErrorFileNotFound;
1539 }
1540 if (copied_amt < buf_len(out_path)) {
1541 buf_resize(out_path, copied_amt);
1542 return ErrorNone;
1543 }
1544 buf_resize(out_path, buf_len(out_path) * 2);
1545 }1589 }
1590 utf16le_ptr_to_utf8(out_path, &path_space.data.items[0]);
1591 return ErrorNone;
15461592
1547#elif defined(ZIG_OS_DARWIN)1593#elif defined(ZIG_OS_DARWIN)
1548 // How long is the executable's path?1594 // How long is the executable's path?
...@@ -1719,6 +1765,15 @@ static uint8_t utf8CodepointSequenceLength(uint32_t c) {...@@ -1719,6 +1765,15 @@ static uint8_t utf8CodepointSequenceLength(uint32_t c) {
1719 zig_unreachable();1765 zig_unreachable();
1720}1766}
17211767
1768// Ported from std.unicode.utf8ByteSequenceLength
1769static uint8_t utf8ByteSequenceLength(uint8_t first_byte) {
1770 if (first_byte < 0b10000000) return 1;
1771 if ((first_byte & 0b11100000) == 0b11000000) return 2;
1772 if ((first_byte & 0b11110000) == 0b11100000) return 3;
1773 if ((first_byte & 0b11111000) == 0b11110000) return 4;
1774 zig_unreachable();
1775}
1776
1722// Ported from std/unicode.zig1777// Ported from std/unicode.zig
1723static size_t utf8Encode(uint32_t c, Slice<uint8_t> out) {1778static size_t utf8Encode(uint32_t c, Slice<uint8_t> out) {
1724 size_t length = utf8CodepointSequenceLength(c);1779 size_t length = utf8CodepointSequenceLength(c);
...@@ -1753,6 +1808,80 @@ static size_t utf8Encode(uint32_t c, Slice<uint8_t> out) {...@@ -1753,6 +1808,80 @@ static size_t utf8Encode(uint32_t c, Slice<uint8_t> out) {
1753 return length;1808 return length;
1754}1809}
17551810
1811// Ported from std.unicode.utf8Decode2
1812static uint32_t utf8Decode2(Slice<uint8_t> bytes) {
1813 assert(bytes.len == 2);
1814 assert((bytes.at(0) & 0b11100000) == 0b11000000);
1815
1816 uint32_t value = bytes.at(0) & 0b00011111;
1817 assert((bytes.at(1) & 0b11000000) == 0b10000000);
1818 value <<= 6;
1819 value |= bytes.at(1) & 0b00111111;
1820
1821 assert(value >= 0x80);
1822 return value;
1823}
1824
1825// Ported from std.unicode.utf8Decode3
1826static uint32_t utf8Decode3(Slice<uint8_t> bytes) {
1827 assert(bytes.len == 3);
1828 assert((bytes.at(0) & 0b11110000) == 0b11100000);
1829
1830 uint32_t value = bytes.at(0) & 0b00001111;
1831 assert((bytes.at(1) & 0b11000000) == 0b10000000);
1832 value <<= 6;
1833 value |= bytes.at(1) & 0b00111111;
1834
1835 assert((bytes.at(2) & 0b11000000) == 0b10000000);
1836 value <<= 6;
1837 value |= bytes.at(2) & 0b00111111;
1838
1839 assert(value >= 0x80);
1840 assert(value < 0xd800 || value > 0xdfff);
1841 return value;
1842}
1843
1844// Ported from std.unicode.utf8Decode4
1845static uint32_t utf8Decode4(Slice<uint8_t> bytes) {
1846 assert(bytes.len == 4);
1847 assert((bytes.at(0) & 0b11111000) == 0b11110000);
1848
1849 uint32_t value = bytes.at(0) & 0b00000111;
1850 assert((bytes.at(1) & 0b11000000) == 0b10000000);
1851 value <<= 6;
1852 value |= bytes.at(1) & 0b00111111;
1853
1854 assert((bytes.at(2) & 0b11000000) == 0b10000000);
1855 value <<= 6;
1856 value |= bytes.at(2) & 0b00111111;
1857
1858 assert((bytes.at(3) & 0b11000000) == 0b10000000);
1859 value <<= 6;
1860 value |= bytes.at(3) & 0b00111111;
1861
1862 assert(value >= 0x10000 && value <= 0x10FFFF);
1863 return value;
1864}
1865
1866// Ported from std.unicode.utf8Decode
1867static uint32_t utf8Decode(Slice<uint8_t> bytes) {
1868 switch (bytes.len) {
1869 case 1:
1870 return bytes.at(0);
1871 break;
1872 case 2:
1873 return utf8Decode2(bytes);
1874 break;
1875 case 3:
1876 return utf8Decode3(bytes);
1877 break;
1878 case 4:
1879 return utf8Decode4(bytes);
1880 break;
1881 default:
1882 zig_unreachable();
1883 }
1884}
1756// Ported from std.unicode.utf16leToUtf8Alloc1885// Ported from std.unicode.utf16leToUtf8Alloc
1757static void utf16le_ptr_to_utf8(Buf *out, WCHAR *utf16le) {1886static void utf16le_ptr_to_utf8(Buf *out, WCHAR *utf16le) {
1758 // optimistically guess that it will all be ascii.1887 // optimistically guess that it will all be ascii.
...@@ -1770,6 +1899,60 @@ static void utf16le_ptr_to_utf8(Buf *out, WCHAR *utf16le) {...@@ -1770,6 +1899,60 @@ static void utf16le_ptr_to_utf8(Buf *out, WCHAR *utf16le) {
1770 out_index += utf8_len;1899 out_index += utf8_len;
1771 }1900 }
1772}1901}
1902
1903// Ported from std.unicode.utf8ToUtf16Le
1904static size_t utf8_to_utf16le(WCHAR *utf16_le, Slice<uint8_t> utf8) {
1905 size_t dest_i = 0;
1906 size_t src_i = 0;
1907 while (src_i < utf8.len) {
1908 uint8_t n = utf8ByteSequenceLength(utf8.at(src_i));
1909 size_t next_src_i = src_i + n;
1910 uint32_t codepoint = utf8Decode(utf8.slice(src_i, next_src_i));
1911 if (codepoint < 0x10000) {
1912 utf16_le[dest_i] = codepoint;
1913 dest_i += 1;
1914 } else {
1915 WCHAR high = ((codepoint - 0x10000) >> 10) + 0xD800;
1916 WCHAR low = (codepoint & 0x3FF) + 0xDC00;
1917 utf16_le[dest_i] = high;
1918 utf16_le[dest_i + 1] = low;
1919 dest_i += 2;
1920 }
1921 src_i = next_src_i;
1922 }
1923 return dest_i;
1924}
1925
1926// Ported from std.os.windows.sliceToPrefixedFileW
1927PathSpace slice_to_prefixed_file_w(Slice<uint8_t> path) {
1928 PathSpace path_space;
1929 for (size_t idx = 0; idx < path.len; idx++) {
1930 assert(path.ptr[idx] != '*' && path.ptr[idx] != '?' && path.ptr[idx] != '"' &&
1931 path.ptr[idx] != '<' && path.ptr[idx] != '>' && path.ptr[idx] != '|');
1932 }
1933
1934 size_t start_index;
1935 if (memStartsWith(path, str("\\?")) || !isAbsoluteWindows(path)) {
1936 start_index = 0;
1937 } else {
1938 static WCHAR prefix[4] = { u'\\', u'?', u'?', u'\\' };
1939 memCopy(path_space.data.slice(), Slice<WCHAR> { prefix, 4 });
1940 start_index = 4;
1941 }
1942
1943 path_space.len = start_index + utf8_to_utf16le(path_space.data.slice().sliceFrom(start_index).ptr, path);
1944 assert(path_space.len <= path_space.data.len);
1945
1946 Slice<WCHAR> path_slice = path_space.data.slice().slice(0, path_space.len);
1947 for (size_t elem_idx = 0; elem_idx < path_slice.len; elem_idx += 1) {
1948 if (path_slice.at(elem_idx) == '/') {
1949 path_slice.at(elem_idx) = '\\';
1950 }
1951 }
1952
1953 path_space.data.items[path_space.len] = 0;
1954 return path_space;
1955}
1773#endif1956#endif
17741957
1775// Ported from std.os.getAppDataDir1958// Ported from std.os.getAppDataDir
...@@ -1862,8 +2045,8 @@ Error os_self_exe_shared_libs(ZigList<Buf *> &paths) {...@@ -1862,8 +2045,8 @@ Error os_self_exe_shared_libs(ZigList<Buf *> &paths) {
18622045
1863Error os_file_open_rw(Buf *full_path, OsFile *out_file, OsFileAttr *attr, bool need_write, uint32_t mode) {2046Error os_file_open_rw(Buf *full_path, OsFile *out_file, OsFileAttr *attr, bool need_write, uint32_t mode) {
1864#if defined(ZIG_OS_WINDOWS)2047#if defined(ZIG_OS_WINDOWS)
1865 // TODO use CreateFileW2048 PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(full_path));
1866 HANDLE result = CreateFileA(buf_ptr(full_path),2049 HANDLE result = CreateFileW(&path_space.data.items[0],
1867 need_write ? (GENERIC_READ|GENERIC_WRITE) : GENERIC_READ,2050 need_write ? (GENERIC_READ|GENERIC_WRITE) : GENERIC_READ,
1868 need_write ? 0 : FILE_SHARE_READ,2051 need_write ? 0 : FILE_SHARE_READ,
1869 nullptr,2052 nullptr,
...@@ -1967,8 +2150,9 @@ Error os_file_open_w(Buf *full_path, OsFile *out_file, OsFileAttr *attr, uint32_...@@ -1967,8 +2150,9 @@ Error os_file_open_w(Buf *full_path, OsFile *out_file, OsFileAttr *attr, uint32_
19672150
1968Error os_file_open_lock_rw(Buf *full_path, OsFile *out_file) {2151Error os_file_open_lock_rw(Buf *full_path, OsFile *out_file) {
1969#if defined(ZIG_OS_WINDOWS)2152#if defined(ZIG_OS_WINDOWS)
2153 PathSpace path_space = slice_to_prefixed_file_w(buf_to_slice(full_path));
1970 for (;;) {2154 for (;;) {
1971 HANDLE result = CreateFileA(buf_ptr(full_path), GENERIC_READ | GENERIC_WRITE,2155 HANDLE result = CreateFileW(&path_space.data.items[0], GENERIC_READ | GENERIC_WRITE,
1972 0, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);2156 0, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
19732157
1974 if (result == INVALID_HANDLE_VALUE) {2158 if (result == INVALID_HANDLE_VALUE) {
src/os.hpp+8
...@@ -155,4 +155,12 @@ Error ATTRIBUTE_MUST_USE os_get_app_data_dir(Buf *out_path, const char *appname)...@@ -155,4 +155,12 @@ Error ATTRIBUTE_MUST_USE os_get_app_data_dir(Buf *out_path, const char *appname)
155155
156Error ATTRIBUTE_MUST_USE os_self_exe_shared_libs(ZigList<Buf *> &paths);156Error ATTRIBUTE_MUST_USE os_self_exe_shared_libs(ZigList<Buf *> &paths);
157157
158const size_t PATH_MAX_WIDE = 32767;
159
160struct PathSpace {
161 Array<wchar_t, PATH_MAX_WIDE> data;
162 size_t len;
163};
164
165PathSpace slice_to_prefixed_file_w(Slice<uint8_t> path);
158#endif166#endif
src/util.hpp+1-1
...@@ -159,7 +159,7 @@ struct Slice {...@@ -159,7 +159,7 @@ struct Slice {
159159
160 inline T &at(size_t i) {160 inline T &at(size_t i) {
161 assert(i < len);161 assert(i < len);
162 return &ptr[i];162 return ptr[i];
163 }163 }
164164
165 inline Slice<T> slice(size_t start, size_t end) {165 inline Slice<T> slice(size_t start, size_t end) {