Browse Source

Begin work on os2/dir.odin

gingerBill 1 year ago
parent
commit
8037ace873

+ 21 - 0
core/os/os2/dir.odin

@@ -0,0 +1,21 @@
+package os2
+
+import "base:runtime"
+
+read_directory :: proc(f: ^File, n: int, allocator: runtime.Allocator) -> (fi: []File_Info, err: Error) {
+	return _read_directory(f, n, allocator)
+}
+
+read_all_directory :: proc(f: ^File, allocator: runtime.Allocator) -> (fi: []File_Info, err: Error) {
+	return read_directory(f, -1, allocator)
+}
+
+read_directory_by_path :: proc(path: string, n: int, allocator: runtime.Allocator) -> (fi: []File_Info, err: Error) {
+	f := open(path) or_return
+	defer close(f)
+	return read_directory(f, n, allocator)
+}
+
+read_all_directory_by_path :: proc(path: string, allocator: runtime.Allocator) -> (fi: []File_Info, err: Error) {
+	return read_directory_by_path(path, -1, allocator)
+}

+ 8 - 0
core/os/os2/dir_linux.odin

@@ -0,0 +1,8 @@
+package os2
+
+import "base:runtime"
+
+@(private)
+_read_directory :: proc(f: ^File, n: int, allocator: runtime.Allocator) -> (files: []File_Info, err: Error) {
+	return
+}

+ 118 - 0
core/os/os2/dir_windows.odin

@@ -0,0 +1,118 @@
+package os2
+
+import "base:runtime"
+import "core:time"
+import win32 "core:sys/windows"
+
+@(private)
+_read_directory :: proc(f: ^File, n: int, allocator: runtime.Allocator) -> (files: []File_Info, err: Error) {
+	find_data_to_file_info :: proc(base_path: string, d: ^win32.WIN32_FIND_DATAW, allocator: runtime.Allocator) -> (fi: File_Info, err: Error) {
+		// Ignore "." and ".."
+		if d.cFileName[0] == '.' && d.cFileName[1] == 0 {
+			return
+		}
+		if d.cFileName[0] == '.' && d.cFileName[1] == '.' && d.cFileName[2] == 0 {
+			return
+		}
+		path := concatenate({base_path, `\`, win32_utf16_to_utf8(d.cFileName[:], temp_allocator()) or_else ""}, allocator) or_return
+		fi.fullpath = path
+		fi.name = basename(path)
+		fi.size = i64(d.nFileSizeHigh)<<32 + i64(d.nFileSizeLow)
+
+		if d.dwFileAttributes & win32.FILE_ATTRIBUTE_READONLY != 0 {
+			fi.mode |= 0o444
+		} else {
+			fi.mode |= 0o666
+		}
+
+		is_sym := false
+		if d.dwFileAttributes & win32.FILE_ATTRIBUTE_REPARSE_Point == 0 {
+			is_sym = false
+		} else {
+			is_sym = d.dwReserved0 == win32.IO_REPARSE_TAG_SYMLINK || d.dwReserved0 == win32.IO_REPARSE_TAG_MOUNT_POINT
+		}
+
+		if is_sym {
+			fi.type = .Symlink
+		} else if d.dwFileAttributes & win32.FILE_ATTRIBUTE_DIRECTORY != 0 {
+			fi.type = .Directory
+			fi.mode |= 0o111
+		}
+
+		fi.creation_time     = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftCreationTime))
+		fi.modification_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastWriteTime))
+		fi.access_time       = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastAccessTime))
+		return
+	}
+
+	if f == nil {
+		return nil, .Invalid_File
+	}
+
+	TEMP_ALLOCATOR_GUARD()
+
+	impl := (^File_Impl)(f.impl)
+
+	if !is_directory(impl.name) {
+		return nil, .Invalid_Dir
+	}
+
+	n := n
+	size := n
+	if n <= 0 {
+		n = -1
+		size = 100
+	}
+
+	wpath: []u16
+	{
+		i := 0
+		for impl.wname[i] != 0 {
+			i += 1
+		}
+		wpath = impl.wname[:i]
+	}
+
+
+	wpath_search := make([]u16, len(wpath)+3, context.temp_allocator)
+	copy(wpath_search, wpath)
+	wpath_search[len(wpath)+0] = '\\'
+	wpath_search[len(wpath)+1] = '*'
+	wpath_search[len(wpath)+2] = 0
+
+	find_data := &win32.WIN32_FIND_DATAW{}
+	find_handle := win32.FindFirstFileW(raw_data(wpath_search), find_data)
+	if find_handle == win32.INVALID_HANDLE_VALUE {
+		return nil, _get_platform_error()
+	}
+	defer win32.FindClose(find_handle)
+
+	path := _cleanpath_from_buf(wpath, temp_allocator()) or_return
+
+	dfi := make([dynamic]File_Info, 0, size, allocator)
+	defer if err != nil {
+		for fi in dfi {
+			file_info_delete(fi, allocator)
+		}
+		delete(dfi)
+	}
+	for n != 0 {
+		fi: File_Info
+		fi = find_data_to_file_info(path, find_data, allocator) or_return
+		if fi.name != "" {
+			append(&dfi, fi)
+			n -= 1
+		}
+
+		if !win32.FindNextFileW(find_handle, find_data) {
+			e := _get_platform_error()
+			if pe, _ := is_platform_error(e); pe == i32(win32.ERROR_NO_MORE_FILES) {
+				break
+			}
+			return dfi[:], e
+		}
+	}
+
+	return dfi[:], nil
+}
+

+ 9 - 6
core/os/os2/env_windows.odin

@@ -8,7 +8,8 @@ _lookup_env :: proc(key: string, allocator: runtime.Allocator) -> (value: string
 	if key == "" {
 	if key == "" {
 		return
 		return
 	}
 	}
-	wkey := win32.utf8_to_wstring(key)
+	TEMP_ALLOCATOR_GUARD()
+	wkey, _ := win32_utf8_to_wstring(key, temp_allocator())
 
 
 	n := win32.GetEnvironmentVariableW(wkey, nil, 0)
 	n := win32.GetEnvironmentVariableW(wkey, nil, 0)
 	if n == 0 {
 	if n == 0 {
@@ -32,20 +33,22 @@ _lookup_env :: proc(key: string, allocator: runtime.Allocator) -> (value: string
 		return "", false
 		return "", false
 	}
 	}
 
 
-	value = win32.utf16_to_utf8(b[:n], allocator) or_else ""
+	value = win32_utf16_to_utf8(b[:n], allocator) or_else ""
 	found = true
 	found = true
 	return
 	return
 }
 }
 
 
 _set_env :: proc(key, value: string) -> bool {
 _set_env :: proc(key, value: string) -> bool {
-	k := win32.utf8_to_wstring(key)
-	v := win32.utf8_to_wstring(value)
+	TEMP_ALLOCATOR_GUARD()
+	k, _ := win32_utf8_to_wstring(key,   temp_allocator())
+	v, _ := win32_utf8_to_wstring(value, temp_allocator())
 
 
 	return bool(win32.SetEnvironmentVariableW(k, v))
 	return bool(win32.SetEnvironmentVariableW(k, v))
 }
 }
 
 
 _unset_env :: proc(key: string) -> bool {
 _unset_env :: proc(key: string) -> bool {
-	k := win32.utf8_to_wstring(key)
+	TEMP_ALLOCATOR_GUARD()
+	k, _ := win32_utf8_to_wstring(key, temp_allocator())
 	return bool(win32.SetEnvironmentVariableW(k, nil))
 	return bool(win32.SetEnvironmentVariableW(k, nil))
 }
 }
 
 
@@ -89,7 +92,7 @@ _environ :: proc(allocator: runtime.Allocator) -> []string {
 				break
 				break
 			}
 			}
 			w := ([^]u16)(p)[from:i]
 			w := ([^]u16)(p)[from:i]
-			append(&r, win32.utf16_to_utf8(w, allocator) or_else "")
+			append(&r, win32_utf16_to_utf8(w, allocator) or_else "")
 			from = i + 1
 			from = i + 1
 		}
 		}
 	}
 	}

+ 99 - 17
core/os/os2/file_windows.odin

@@ -61,7 +61,7 @@ _open_internal :: proc(name: string, flags: File_Flags, perm: int) -> (handle: u
 		return
 		return
 	}
 	}
 
 
-	path := _fix_long_path(name)
+	path := _fix_long_path(name) or_return
 	access: u32
 	access: u32
 	switch flags & {.Read, .Write} {
 	switch flags & {.Read, .Write} {
 	case {.Read}:         access = win32.FILE_GENERIC_READ
 	case {.Read}:         access = win32.FILE_GENERIC_READ
@@ -138,7 +138,7 @@ _new_file :: proc(handle: uintptr, name: string) -> ^File {
 	impl.allocator = file_allocator()
 	impl.allocator = file_allocator()
 	impl.fd = rawptr(handle)
 	impl.fd = rawptr(handle)
 	impl.name, _ = clone_string(name, impl.allocator)
 	impl.name, _ = clone_string(name, impl.allocator)
-	impl.wname = win32.utf8_to_wstring(name, impl.allocator)
+	impl.wname, _ = win32_utf8_to_wstring(name, impl.allocator)
 
 
 	handle := _handle(&impl.file)
 	handle := _handle(&impl.file)
 	kind := File_Impl_Kind.File
 	kind := File_Impl_Kind.File
@@ -452,7 +452,7 @@ _truncate :: proc(f: ^File, size: i64) -> Error {
 }
 }
 
 
 _remove :: proc(name: string) -> Error {
 _remove :: proc(name: string) -> Error {
-	p := _fix_long_path(name)
+	p := _fix_long_path(name) or_return
 	err, err1: Error
 	err, err1: Error
 	if !win32.DeleteFileW(p) {
 	if !win32.DeleteFileW(p) {
 		err = _get_platform_error()
 		err = _get_platform_error()
@@ -489,8 +489,8 @@ _remove :: proc(name: string) -> Error {
 }
 }
 
 
 _rename :: proc(old_path, new_path: string) -> Error {
 _rename :: proc(old_path, new_path: string) -> Error {
-	from := _fix_long_path(old_path)
-	to := _fix_long_path(new_path)
+	from := _fix_long_path(old_path) or_return
+	to   := _fix_long_path(new_path) or_return
 	if win32.MoveFileExW(from, to, win32.MOVEFILE_REPLACE_EXISTING) {
 	if win32.MoveFileExW(from, to, win32.MOVEFILE_REPLACE_EXISTING) {
 		return nil
 		return nil
 	}
 	}
@@ -499,8 +499,8 @@ _rename :: proc(old_path, new_path: string) -> Error {
 }
 }
 
 
 _link :: proc(old_name, new_name: string) -> Error {
 _link :: proc(old_name, new_name: string) -> Error {
-	o := _fix_long_path(old_name)
-	n := _fix_long_path(new_name)
+	o := _fix_long_path(old_name) or_return
+	n := _fix_long_path(new_name) or_return
 	if win32.CreateHardLinkW(n, o, nil) {
 	if win32.CreateHardLinkW(n, o, nil) {
 		return nil
 		return nil
 	}
 	}
@@ -540,16 +540,16 @@ _normalize_link_path :: proc(p: []u16, allocator: runtime.Allocator) -> (str: st
 	}
 	}
 
 
 	if !has_unc_prefix(p) {
 	if !has_unc_prefix(p) {
-		return win32.utf16_to_utf8(p, allocator)
+		return win32_utf16_to_utf8(p, allocator)
 	}
 	}
 
 
 	ws := p[4:]
 	ws := p[4:]
 	switch {
 	switch {
 	case len(ws) >= 2 && ws[1] == ':':
 	case len(ws) >= 2 && ws[1] == ':':
-		return win32.utf16_to_utf8(ws, allocator)
+		return win32_utf16_to_utf8(ws, allocator)
 	case has_prefix(ws, `UNC\`):
 	case has_prefix(ws, `UNC\`):
 		ws[3] = '\\' // override data in buffer
 		ws[3] = '\\' // override data in buffer
-		return win32.utf16_to_utf8(ws[3:], allocator)
+		return win32_utf16_to_utf8(ws[3:], allocator)
 	}
 	}
 
 
 
 
@@ -574,9 +574,9 @@ _normalize_link_path :: proc(p: []u16, allocator: runtime.Allocator) -> (str: st
 		ws = ws[4:]
 		ws = ws[4:]
 		if len(ws) > 3 && has_prefix(ws, `UNC`) {
 		if len(ws) > 3 && has_prefix(ws, `UNC`) {
 			ws[2] = '\\'
 			ws[2] = '\\'
-			return win32.utf16_to_utf8(ws[2:], allocator)
+			return win32_utf16_to_utf8(ws[2:], allocator)
 		}
 		}
-		return win32.utf16_to_utf8(ws, allocator)
+		return win32_utf16_to_utf8(ws, allocator)
 	}
 	}
 	return "", .Invalid_Path
 	return "", .Invalid_Path
 }
 }
@@ -587,8 +587,8 @@ _read_link :: proc(name: string, allocator: runtime.Allocator) -> (s: string, er
 	@thread_local
 	@thread_local
 	rdb_buf: [MAXIMUM_REPARSE_DATA_BUFFER_SIZE]byte
 	rdb_buf: [MAXIMUM_REPARSE_DATA_BUFFER_SIZE]byte
 
 
-	p := _fix_long_path(name)
-	handle := _open_sym_link(p) or_return
+	p      := _fix_long_path(name) or_return
+	handle := _open_sym_link(p)    or_return
 	defer win32.CloseHandle(handle)
 	defer win32.CloseHandle(handle)
 
 
 	bytes_returned: u32
 	bytes_returned: u32
@@ -607,7 +607,7 @@ _read_link :: proc(name: string, allocator: runtime.Allocator) -> (s: string, er
 		pb[rb.SubstituteNameOffset+rb.SubstituteNameLength] = 0
 		pb[rb.SubstituteNameOffset+rb.SubstituteNameLength] = 0
 		p := pb[rb.SubstituteNameOffset:][:rb.SubstituteNameLength]
 		p := pb[rb.SubstituteNameOffset:][:rb.SubstituteNameLength]
 		if rb.Flags & win32.SYMLINK_FLAG_RELATIVE != 0 {
 		if rb.Flags & win32.SYMLINK_FLAG_RELATIVE != 0 {
-			return win32.utf16_to_utf8(p, allocator)
+			return win32_utf16_to_utf8(p, allocator)
 		}
 		}
 		return _normalize_link_path(p, allocator)
 		return _normalize_link_path(p, allocator)
 
 
@@ -662,7 +662,7 @@ _fchown :: proc(f: ^File, uid, gid: int) -> Error {
 }
 }
 
 
 _chdir :: proc(name: string) -> Error {
 _chdir :: proc(name: string) -> Error {
-	p := _fix_long_path(name)
+	p := _fix_long_path(name) or_return
 	if !win32.SetCurrentDirectoryW(p) {
 	if !win32.SetCurrentDirectoryW(p) {
 		return _get_platform_error()
 		return _get_platform_error()
 	}
 	}
@@ -718,7 +718,7 @@ _fchtimes :: proc(f: ^File, atime, mtime: time.Time) -> Error {
 }
 }
 
 
 _exists :: proc(path: string) -> bool {
 _exists :: proc(path: string) -> bool {
-	wpath := _fix_long_path(path)
+	wpath, _ := _fix_long_path(path)
 	attribs := win32.GetFileAttributesW(wpath)
 	attribs := win32.GetFileAttributesW(wpath)
 	return attribs != win32.INVALID_FILE_ATTRIBUTES
 	return attribs != win32.INVALID_FILE_ATTRIBUTES
 }
 }
@@ -766,3 +766,85 @@ _file_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte,
 	return 0, .Empty
 	return 0, .Empty
 }
 }
 
 
+
+
+@(private="package", require_results)
+win32_utf8_to_wstring :: proc(s: string, allocator: runtime.Allocator) -> (ws: [^]u16, err: runtime.Allocator_Error) {
+	ws = raw_data(win32_utf8_to_utf16(s, allocator) or_return)
+	return
+}
+
+@(private="package", require_results)
+win32_utf8_to_utf16 :: proc(s: string, allocator: runtime.Allocator) -> (ws: []u16, err: runtime.Allocator_Error) {
+	if len(s) < 1 {
+		return
+	}
+
+	b := transmute([]byte)s
+	cstr := raw_data(b)
+	n := win32.MultiByteToWideChar(win32.CP_UTF8, win32.MB_ERR_INVALID_CHARS, cstr, i32(len(s)), nil, 0)
+	if n == 0 {
+		return nil, nil
+	}
+
+	text := make([]u16, n+1, allocator) or_return
+
+	n1 := win32.MultiByteToWideChar(win32.CP_UTF8, win32.MB_ERR_INVALID_CHARS, cstr, i32(len(s)), raw_data(text), n)
+	if n1 == 0 {
+		delete(text, allocator)
+		return
+	}
+
+	text[n] = 0
+	for n >= 1 && text[n-1] == 0 {
+		n -= 1
+	}
+	ws = text[:n]
+	return
+}
+
+@(private="package", require_results)
+win32_wstring_to_utf8 :: proc(s: [^]u16, allocator: runtime.Allocator) -> (res: string, err: runtime.Allocator_Error) {
+	if s == nil || s[0] == 0 {
+		return "", nil
+	}
+	n := 0
+	for s[n] != 0 {
+		n += 1
+	}
+	return win32_utf16_to_utf8(s[:n], allocator)
+}
+
+@(private="package", require_results)
+win32_utf16_to_utf8 :: proc(s: []u16, allocator: runtime.Allocator) -> (res: string, err: runtime.Allocator_Error) {
+	if len(s) == 0 {
+		return
+	}
+
+	n := win32.WideCharToMultiByte(win32.CP_UTF8, win32.WC_ERR_INVALID_CHARS, raw_data(s), i32(len(s)), nil, 0, nil, nil)
+	if n == 0 {
+		return
+	}
+
+	// If N < 0 the call to WideCharToMultiByte assume the wide string is null terminated
+	// and will scan it to find the first null terminated character. The resulting string will
+	// also be null terminated.
+	// If N > 0 it assumes the wide string is not null terminated and the resulting string
+	// will not be null terminated.
+	text := make([]byte, n, allocator) or_return
+
+	n1 := win32.WideCharToMultiByte(win32.CP_UTF8, win32.WC_ERR_INVALID_CHARS, raw_data(s), i32(len(s)), raw_data(text), n, nil, nil)
+	if n1 == 0 {
+		delete(text, allocator)
+		return
+	}
+
+	for i in 0..<n {
+		if text[i] == 0 {
+			n = i
+			break
+		}
+	}
+	res = string(text[:n])
+	return
+}

+ 2 - 0
core/os/os2/internal_util.odin

@@ -126,3 +126,5 @@ random_string :: proc(buf: []byte) -> string {
 	buf[i] = digits[u % b]
 	buf[i] = digits[u % b]
 	return string(buf[i:])
 	return string(buf[i:])
 }
 }
+
+

+ 8 - 5
core/os/os2/path_windows.odin

@@ -13,7 +13,7 @@ _is_path_separator :: proc(c: byte) -> bool {
 }
 }
 
 
 _mkdir :: proc(name: string, perm: int) -> Error {
 _mkdir :: proc(name: string, perm: int) -> Error {
-	if !win32.CreateDirectoryW(_fix_long_path(name), nil) {
+	if !win32.CreateDirectoryW(_fix_long_path(name) or_return, nil) {
 		return _get_platform_error()
 		return _get_platform_error()
 	}
 	}
 	return nil
 	return nil
@@ -95,14 +95,17 @@ init_long_path_support :: proc() {
 	can_use_long_paths = false
 	can_use_long_paths = false
 }
 }
 
 
-_fix_long_path_slice :: proc(path: string) -> []u16 {
-	return win32.utf8_to_utf16(_fix_long_path_internal(path))
+@(require_results)
+_fix_long_path_slice :: proc(path: string) -> ([]u16, runtime.Allocator_Error) {
+	return win32_utf8_to_utf16(_fix_long_path_internal(path), temp_allocator())
 }
 }
 
 
-_fix_long_path :: proc(path: string) -> win32.wstring {
-	return win32.utf8_to_wstring(_fix_long_path_internal(path))
+@(require_results)
+_fix_long_path :: proc(path: string) -> (win32.wstring, runtime.Allocator_Error) {
+	return win32_utf8_to_wstring(_fix_long_path_internal(path), temp_allocator())
 }
 }
 
 
+@(require_results)
 _fix_long_path_internal :: proc(path: string) -> string {
 _fix_long_path_internal :: proc(path: string) -> string {
 	if can_use_long_paths {
 	if can_use_long_paths {
 		return path
 		return path

+ 14 - 14
core/os/os2/process_windows.odin

@@ -163,7 +163,7 @@ _process_info_by_pid :: proc(pid: int, selection: Process_Info_Fields, allocator
 			_ = read_memory_as_slice(ph, process_params.CommandLine.Buffer, cmdline_w) or_return
 			_ = read_memory_as_slice(ph, process_params.CommandLine.Buffer, cmdline_w) or_return
 
 
 			if .Command_Line in selection {
 			if .Command_Line in selection {
-				info.command_line = win32.utf16_to_utf8(cmdline_w, allocator) or_return
+				info.command_line = win32_utf16_to_utf8(cmdline_w, allocator) or_return
 				info.fields += {.Command_Line}
 				info.fields += {.Command_Line}
 			}
 			}
 			if .Command_Args in selection {
 			if .Command_Args in selection {
@@ -185,7 +185,7 @@ _process_info_by_pid :: proc(pid: int, selection: Process_Info_Fields, allocator
 			cwd_w := make([]u16, process_params.CurrentDirectoryPath.Length, temp_allocator()) or_return
 			cwd_w := make([]u16, process_params.CurrentDirectoryPath.Length, temp_allocator()) or_return
 			_ = read_memory_as_slice(ph, process_params.CurrentDirectoryPath.Buffer, cwd_w) or_return
 			_ = read_memory_as_slice(ph, process_params.CurrentDirectoryPath.Buffer, cwd_w) or_return
 
 
-			info.working_dir = win32.utf16_to_utf8(cwd_w, allocator) or_return
+			info.working_dir = win32_utf16_to_utf8(cwd_w, allocator) or_return
 			info.fields += {.Working_Dir}
 			info.fields += {.Working_Dir}
 		}
 		}
 	}
 	}
@@ -255,7 +255,7 @@ _process_info_by_handle :: proc(process: Process, selection: Process_Info_Fields
 			_ = read_memory_as_slice(ph, process_params.CommandLine.Buffer, cmdline_w) or_return
 			_ = read_memory_as_slice(ph, process_params.CommandLine.Buffer, cmdline_w) or_return
 
 
 			if .Command_Line in selection {
 			if .Command_Line in selection {
-				info.command_line = win32.utf16_to_utf8(cmdline_w, allocator) or_return
+				info.command_line = win32_utf16_to_utf8(cmdline_w, allocator) or_return
 				info.fields += {.Command_Line}
 				info.fields += {.Command_Line}
 			}
 			}
 			if .Command_Args in selection {
 			if .Command_Args in selection {
@@ -279,7 +279,7 @@ _process_info_by_handle :: proc(process: Process, selection: Process_Info_Fields
 			cwd_w := make([]u16, process_params.CurrentDirectoryPath.Length, temp_allocator()) or_return
 			cwd_w := make([]u16, process_params.CurrentDirectoryPath.Length, temp_allocator()) or_return
 			_ = read_memory_as_slice(ph, process_params.CurrentDirectoryPath.Buffer, cwd_w) or_return
 			_ = read_memory_as_slice(ph, process_params.CurrentDirectoryPath.Buffer, cwd_w) or_return
 
 
-			info.working_dir = win32.utf16_to_utf8(cwd_w, allocator) or_return
+			info.working_dir = win32_utf16_to_utf8(cwd_w, allocator) or_return
 			info.fields += {.Working_Dir}
 			info.fields += {.Working_Dir}
 		}
 		}
 	}
 	}
@@ -316,13 +316,13 @@ _current_process_info :: proc(selection: Process_Info_Fields, allocator: runtime
 	if .Executable_Path in selection {
 	if .Executable_Path in selection {
 		exe_filename_w: [256]u16
 		exe_filename_w: [256]u16
 		path_len := win32.GetModuleFileNameW(nil, raw_data(exe_filename_w[:]), len(exe_filename_w))
 		path_len := win32.GetModuleFileNameW(nil, raw_data(exe_filename_w[:]), len(exe_filename_w))
-		info.executable_path = win32.utf16_to_utf8(exe_filename_w[:path_len], allocator) or_return
+		info.executable_path = win32_utf16_to_utf8(exe_filename_w[:path_len], allocator) or_return
 		info.fields += {.Executable_Path}
 		info.fields += {.Executable_Path}
 	}
 	}
 	if selection >= {.Command_Line,  .Command_Args} {
 	if selection >= {.Command_Line,  .Command_Args} {
 		command_line_w := win32.GetCommandLineW()
 		command_line_w := win32.GetCommandLineW()
 		if .Command_Line in selection {
 		if .Command_Line in selection {
-			info.command_line = win32.wstring_to_utf8(command_line_w, -1, allocator) or_return
+			info.command_line = win32_wstring_to_utf8(command_line_w, allocator) or_return
 			info.fields += {.Command_Line}
 			info.fields += {.Command_Line}
 		}
 		}
 		if .Command_Args in selection {
 		if .Command_Args in selection {
@@ -380,13 +380,13 @@ _Sys_Process_Attributes :: struct {}
 _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) {
 _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) {
 	TEMP_ALLOCATOR_GUARD()
 	TEMP_ALLOCATOR_GUARD()
 	command_line   := _build_command_line(desc.command, temp_allocator())
 	command_line   := _build_command_line(desc.command, temp_allocator())
-	command_line_w := win32.utf8_to_wstring(command_line, temp_allocator())
+	command_line_w := win32_utf8_to_wstring(command_line, temp_allocator()) or_return
 	environment := desc.env
 	environment := desc.env
 	if desc.env == nil {
 	if desc.env == nil {
 		environment = environ(temp_allocator())
 		environment = environ(temp_allocator())
 	}
 	}
 	environment_block   := _build_environment_block(environment, temp_allocator())
 	environment_block   := _build_environment_block(environment, temp_allocator())
-	environment_block_w := win32.utf8_to_utf16(environment_block, temp_allocator())
+	environment_block_w := win32_utf8_to_utf16(environment_block, temp_allocator()) or_return
 	stderr_handle       := win32.GetStdHandle(win32.STD_ERROR_HANDLE)
 	stderr_handle       := win32.GetStdHandle(win32.STD_ERROR_HANDLE)
 	stdout_handle       := win32.GetStdHandle(win32.STD_OUTPUT_HANDLE)
 	stdout_handle       := win32.GetStdHandle(win32.STD_OUTPUT_HANDLE)
 	stdin_handle        := win32.GetStdHandle(win32.STD_INPUT_HANDLE)
 	stdin_handle        := win32.GetStdHandle(win32.STD_INPUT_HANDLE)
@@ -401,7 +401,7 @@ _process_start :: proc(desc: Process_Desc) -> (process: Process, err: Error) {
 		stdin_handle = win32.HANDLE((^File_Impl)(desc.stderr.impl).fd)
 		stdin_handle = win32.HANDLE((^File_Impl)(desc.stderr.impl).fd)
 	}
 	}
 
 
-	working_dir_w := win32.utf8_to_wstring(desc.working_dir, temp_allocator()) if len(desc.working_dir) > 0 else nil
+	working_dir_w := (win32_utf8_to_wstring(desc.working_dir, temp_allocator()) or_else nil) if len(desc.working_dir) > 0 else nil
 	process_info: win32.PROCESS_INFORMATION
 	process_info: win32.PROCESS_INFORMATION
 	ok := win32.CreateProcessW(
 	ok := win32.CreateProcessW(
 		nil,
 		nil,
@@ -535,7 +535,7 @@ _process_exe_by_pid :: proc(pid: int, allocator: runtime.Allocator) -> (exe_path
 		err =_get_platform_error()
 		err =_get_platform_error()
 		return
 		return
 	}
 	}
-	return win32.wstring_to_utf8(raw_data(entry.szExePath[:]), -1, allocator)
+	return win32_wstring_to_utf8(raw_data(entry.szExePath[:]), allocator)
 }
 }
 
 
 _get_process_user :: proc(process_handle: win32.HANDLE, allocator: runtime.Allocator) -> (full_username: string, err: Error) {
 _get_process_user :: proc(process_handle: win32.HANDLE, allocator: runtime.Allocator) -> (full_username: string, err: Error) {
@@ -570,8 +570,8 @@ _get_process_user :: proc(process_handle: win32.HANDLE, allocator: runtime.Alloc
 		err = _get_platform_error()
 		err = _get_platform_error()
 		return
 		return
 	}
 	}
-	username := win32.utf16_to_utf8(username_w[:username_chrs], temp_allocator()) or_return
-	domain   := win32.utf16_to_utf8(domain_w[:domain_chrs], temp_allocator()) or_return
+	username := win32_utf16_to_utf8(username_w[:username_chrs], temp_allocator()) or_return
+	domain   := win32_utf16_to_utf8(domain_w[:domain_chrs], temp_allocator()) or_return
 	return strings.concatenate({domain, "\\", username}, allocator)
 	return strings.concatenate({domain, "\\", username}, allocator)
 }
 }
 
 
@@ -589,7 +589,7 @@ _parse_command_line :: proc(cmd_line_w: [^]u16, allocator: runtime.Allocator) ->
 		delete(argv, allocator)
 		delete(argv, allocator)
 	}
 	}
 	for arg_w, i in argv_w[:argc] {
 	for arg_w, i in argv_w[:argc] {
-		argv[i] = win32.wstring_to_utf8(arg_w, -1, allocator) or_return
+		argv[i] = win32_wstring_to_utf8(arg_w, allocator) or_return
 	}
 	}
 	return
 	return
 }
 }
@@ -665,7 +665,7 @@ _parse_environment_block :: proc(block: [^]u16, allocator: runtime.Allocator) ->
 			idx += 1
 			idx += 1
 		}
 		}
 		env_w := block[last_idx:idx]
 		env_w := block[last_idx:idx]
-		envs[env_idx] = win32.utf16_to_utf8(env_w, allocator) or_return
+		envs[env_idx] = win32_utf16_to_utf8(env_w, allocator) or_return
 		env_idx += 1
 		env_idx += 1
 		idx += 1
 		idx += 1
 		last_idx = idx
 		last_idx = idx

+ 2 - 2
core/os/os2/stat.odin

@@ -57,7 +57,7 @@ same_file :: proc(fi1, fi2: File_Info) -> bool {
 
 
 
 
 last_write_time         :: modification_time
 last_write_time         :: modification_time
-last_write_time_by_name :: modification_time_by_name
+last_write_time_by_name :: modification_time_by_path
 
 
 @(require_results)
 @(require_results)
 modification_time :: proc(f: ^File) -> (time.Time, Error) {
 modification_time :: proc(f: ^File) -> (time.Time, Error) {
@@ -67,7 +67,7 @@ modification_time :: proc(f: ^File) -> (time.Time, Error) {
 }
 }
 
 
 @(require_results)
 @(require_results)
-modification_time_by_name :: proc(path: string) -> (time.Time, Error) {
+modification_time_by_path :: proc(path: string) -> (time.Time, Error) {
 	TEMP_ALLOCATOR_GUARD()
 	TEMP_ALLOCATOR_GUARD()
 	fi, err := stat(path, temp_allocator())
 	fi, err := stat(path, temp_allocator())
 	return fi.modification_time, err
 	return fi.modification_time, err

+ 4 - 4
core/os/os2/stat_windows.odin

@@ -49,7 +49,7 @@ full_path_from_name :: proc(name: string, allocator: runtime.Allocator) -> (path
 	}
 	}
 	TEMP_ALLOCATOR_GUARD()
 	TEMP_ALLOCATOR_GUARD()
 
 
-	p := win32.utf8_to_utf16(name, temp_allocator())
+	p := win32_utf8_to_utf16(name, temp_allocator()) or_return
 
 
 	n := win32.GetFullPathNameW(raw_data(p), 0, nil, nil)
 	n := win32.GetFullPathNameW(raw_data(p), 0, nil, nil)
 	if n == 0 {
 	if n == 0 {
@@ -60,7 +60,7 @@ full_path_from_name :: proc(name: string, allocator: runtime.Allocator) -> (path
 	if n == 0 {
 	if n == 0 {
 		return "", _get_platform_error()
 		return "", _get_platform_error()
 	}
 	}
-	return win32.utf16_to_utf8(buf[:n], allocator)
+	return win32_utf16_to_utf8(buf[:n], allocator)
 }
 }
 
 
 internal_stat :: proc(name: string, create_file_attributes: u32, allocator: runtime.Allocator) -> (fi: File_Info, e: Error) {
 internal_stat :: proc(name: string, create_file_attributes: u32, allocator: runtime.Allocator) -> (fi: File_Info, e: Error) {
@@ -68,7 +68,7 @@ internal_stat :: proc(name: string, create_file_attributes: u32, allocator: runt
 		return {}, .Not_Exist
 		return {}, .Not_Exist
 	}
 	}
 
 
-	wname := _fix_long_path(name)
+	wname := _fix_long_path(name) or_return
 	fa: win32.WIN32_FILE_ATTRIBUTE_DATA
 	fa: win32.WIN32_FILE_ATTRIBUTE_DATA
 	ok := win32.GetFileAttributesExW(wname, win32.GetFileExInfoStandard, &fa)
 	ok := win32.GetFileAttributesExW(wname, win32.GetFileExInfoStandard, &fa)
 	if ok && fa.dwFileAttributes & win32.FILE_ATTRIBUTE_REPARSE_POINT == 0 {
 	if ok && fa.dwFileAttributes & win32.FILE_ATTRIBUTE_REPARSE_POINT == 0 {
@@ -154,7 +154,7 @@ _cleanpath_from_handle_u16 :: proc(f: ^File) -> ([]u16, Error) {
 _cleanpath_from_buf :: proc(buf: []u16, allocator: runtime.Allocator) -> (string, runtime.Allocator_Error) {
 _cleanpath_from_buf :: proc(buf: []u16, allocator: runtime.Allocator) -> (string, runtime.Allocator_Error) {
 	buf := buf
 	buf := buf
 	buf = _cleanpath_strip_prefix(buf)
 	buf = _cleanpath_strip_prefix(buf)
-	return win32.utf16_to_utf8(buf, allocator)
+	return win32_utf16_to_utf8(buf, allocator)
 }
 }
 
 
 basename :: proc(name: string) -> (base: string) {
 basename :: proc(name: string) -> (base: string) {

+ 1 - 1
core/os/os2/temp_file_windows.odin

@@ -19,5 +19,5 @@ _temp_dir :: proc(allocator: runtime.Allocator) -> (string, runtime.Allocator_Er
 	} else if n > 0 && b[n-1] == '\\' {
 	} else if n > 0 && b[n-1] == '\\' {
 		n -= 1
 		n -= 1
 	}
 	}
-	return win32.utf16_to_utf8(b[:n], allocator)
+	return win32_utf16_to_utf8(b[:n], allocator)
 }
 }