From 79b585ada897169c56c7183806a9a811c96c3140 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 21 Feb 2019 21:45:33 +0000 Subject: Add minor additions to mem, sync, and sys/win32 --- core/sys/win32/kernel32.odin | 45 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) (limited to 'core/sys') diff --git a/core/sys/win32/kernel32.odin b/core/sys/win32/kernel32.odin index a41fe32de..6f9390cc4 100644 --- a/core/sys/win32/kernel32.odin +++ b/core/sys/win32/kernel32.odin @@ -56,8 +56,8 @@ foreign kernel32 { @(link_name="GetFileSizeEx") get_file_size_ex :: proc(file_handle: Handle, file_size: ^i64) -> Bool ---; @(link_name="GetFileAttributesA") get_file_attributes_a :: proc(filename: cstring) -> u32 ---; @(link_name="GetFileAttributesW") get_file_attributes_w :: proc(filename: Wstring) -> u32 ---; - @(link_name="GetFileAttributesExA") get_file_attributes_ex_a :: proc(filename: cstring, info_level_id: GET_FILEEX_INFO_LEVELS, file_info: rawptr) -> Bool ---; - @(link_name="GetFileAttributesExW") get_file_attributes_ex_w :: proc(filename: Wstring, info_level_id: GET_FILEEX_INFO_LEVELS, file_info: rawptr) -> Bool ---; + @(link_name="GetFileAttributesExA") get_file_attributes_ex_a :: proc(filename: cstring, info_level_id: GET_FILEEX_INFO_LEVELS, file_info: ^File_Attribute_Data) -> Bool ---; + @(link_name="GetFileAttributesExW") get_file_attributes_ex_w :: proc(filename: Wstring, info_level_id: GET_FILEEX_INFO_LEVELS, file_info: ^File_Attribute_Data) -> Bool ---; @(link_name="GetFileInformationByHandle") get_file_information_by_handle :: proc(file_handle: Handle, file_info: ^By_Handle_File_Information) -> Bool ---; @(link_name="CreateDirectoryA") create_directory_a :: proc(path: cstring, security_attributes: ^Security_Attributes) -> Bool ---; @@ -168,3 +168,44 @@ foreign kernel32 { @(link_name="GetProcAddress") get_proc_address :: proc(h: Hmodule, c_str: cstring) -> rawptr ---; } + +Memory_Basic_Information :: struct { + base_address: rawptr, + allocation_base: rawptr, + allocation_protect: u32, + region_size: uint, + state: u32, + protect: u32, + type: u32, +} + +@(default_calling_convention = "std") +foreign kernel32 { + @(link_name="VirtualAlloc") virtual_alloc :: proc(address: rawptr, size: uint, allocation_type: u32, protect: u32) -> rawptr --- + @(link_name="VirtualAllocEx") virtual_alloc_ex :: proc(process: Handle, address: rawptr, size: uint, allocation_type: u32, protect: u32) -> rawptr --- + @(link_name="VirtualFree") virtual_free :: proc(address: rawptr, size: uint, free_type: u32) -> Bool --- + @(link_name="VirtualLock") virtual_lock :: proc(address: rawptr, size: uint) -> Bool --- + @(link_name="VirtualProtect") virtual_protect :: proc(address: rawptr, size: uint, new_protect: u32, old_protect: ^u32) -> Bool --- + @(link_name="VirtualQuery") virtual_query :: proc(address: rawptr, buffer: ^Memory_Basic_Information, length: uint) -> uint --- +} + +MEM_COMMIT :: 0x00001000; +MEM_RESERVE :: 0x00002000; +MEM_DECOMMIT :: 0x00004000; +MEM_RELEASE :: 0x00008000; +MEM_RESET :: 0x00080000; +MEM_RESET_UNDO :: 0x01000000; + +MEM_LARGE_PAGES :: 0x20000000; +MEM_PHYSICAL :: 0x00400000; +MEM_TOP_DOWN :: 0x00100000; +MEM_WRITE_WATCH :: 0x00200000; + +PAGE_NOACCESS :: 0x01; +PAGE_READONLY :: 0x02; +PAGE_READWRITE :: 0x04; +PAGE_WRITECOPY :: 0x08; +PAGE_EXECUTE :: 0x10; +PAGE_EXECUTE_READ :: 0x20; +PAGE_EXECUTE_READWRITE :: 0x40; +PAGE_EXECUTE_WRITECOPY :: 0x80; -- cgit v1.2.3 From 9b4b20e8b11850dc1c0bbd6751e4d4fc2dc04c1a Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 3 Mar 2019 12:08:26 +0000 Subject: package dynlib --- core/dynlib/lib.odin | 3 +++ core/dynlib/lib_windows.odin | 24 ++++++++++++++++++++++++ core/sys/win32/kernel32.odin | 2 +- core/unicode/utf8/utf8.odin | 2 +- 4 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 core/dynlib/lib.odin create mode 100644 core/dynlib/lib_windows.odin (limited to 'core/sys') diff --git a/core/dynlib/lib.odin b/core/dynlib/lib.odin new file mode 100644 index 000000000..66742b835 --- /dev/null +++ b/core/dynlib/lib.odin @@ -0,0 +1,3 @@ +package dynlib + +Library :: opaque rawptr; diff --git a/core/dynlib/lib_windows.odin b/core/dynlib/lib_windows.odin new file mode 100644 index 000000000..67ce47cc1 --- /dev/null +++ b/core/dynlib/lib_windows.odin @@ -0,0 +1,24 @@ +package dynlib + +import "core:sys/win32" +import "core:strings" + +load_library :: proc(path: string, global_symbols := false) -> (Library, bool) { + // NOTE(bill): 'global_symbols' is here only for consistency with POSIX which has RTLD_GLOBAL + + wide_path := win32.utf8_to_wstring(path, context.temp_allocator); + handle := cast(Library)win32.load_library_w(wide_path); + return handle, handle != nil; +} + +unload_library :: proc(library: Library) -> bool { + ok := win32.free_library(cast(win32.Hmodule)library); + return bool(ok); +} + +symbol_address :: proc(library: Library, symbol: string) -> (ptr: rawptr, found: bool) { + c_str := strings.new_cstring(symbol, context.temp_allocator); + ptr = win32.get_proc_address(cast(win32.Hmodule)library, c_str); + found == ptr != nil; + return; +} diff --git a/core/sys/win32/kernel32.odin b/core/sys/win32/kernel32.odin index 6f9390cc4..33ef0e8b7 100644 --- a/core/sys/win32/kernel32.odin +++ b/core/sys/win32/kernel32.odin @@ -164,7 +164,7 @@ foreign kernel32 { @(link_name="LoadLibraryA") load_library_a :: proc(c_str: cstring) -> Hmodule ---; @(link_name="LoadLibraryW") load_library_w :: proc(c_str: Wstring) -> Hmodule ---; - @(link_name="FreeLibrary") free_library :: proc(h: Hmodule) ---; + @(link_name="FreeLibrary") free_library :: proc(h: Hmodule) -> Bool ---; @(link_name="GetProcAddress") get_proc_address :: proc(h: Hmodule, c_str: cstring) -> rawptr ---; } diff --git a/core/unicode/utf8/utf8.odin b/core/unicode/utf8/utf8.odin index 50b33a680..d0396b9e0 100644 --- a/core/unicode/utf8/utf8.odin +++ b/core/unicode/utf8/utf8.odin @@ -90,7 +90,7 @@ encode_rune :: proc(r: rune) -> ([4]u8, int) { buf[0] = 0xf0 | u8(r>>18); buf[1] = 0x80 | u8(r>>12) & mask; buf[2] = 0x80 | u8(r>>6) & mask; - buf[3] = 0x80 | u8(r) & mask; + buf[3] = 0x80 | u8(r) & mask; return buf, 4; } -- cgit v1.2.3 From d852b0c9485267f247210f3a2f8021e8e2c96232 Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Sat, 9 Mar 2019 11:08:50 +0100 Subject: Add win32.get_cwd to return the current working directory --- core/strings/strings.odin | 17 +++++++++++++++++ core/sys/win32/crt.odin | 14 ++++++++++++++ core/sys/win32/general.odin | 3 +++ 3 files changed, 34 insertions(+) create mode 100644 core/sys/win32/crt.odin (limited to 'core/sys') diff --git a/core/strings/strings.odin b/core/strings/strings.odin index c8c8e560c..edf288c16 100644 --- a/core/strings/strings.odin +++ b/core/strings/strings.odin @@ -329,6 +329,10 @@ is_space :: proc(r: rune) -> bool { return false; } +is_null :: proc(r: rune) -> bool { + return r == 0x0000; +} + index_proc :: proc(s: string, p: proc(rune) -> bool, truth := true) -> int { for r, i in s { if p(r) == truth { @@ -476,3 +480,16 @@ trim_right_space :: proc(s: string) -> string { trim_space :: proc(s: string) -> string { return trim_right_space(trim_left_space(s)); } + +trim_left_null :: proc(s: string) -> string { + return trim_left_proc(s, is_null); +} + +trim_right_null :: proc(s: string) -> string { + return trim_right_proc(s, is_null); +} + +trim_null :: proc(s: string) -> string { + return trim_right_null(trim_left_null(s)); +} + diff --git a/core/sys/win32/crt.odin b/core/sys/win32/crt.odin new file mode 100644 index 000000000..46fba6fe8 --- /dev/null +++ b/core/sys/win32/crt.odin @@ -0,0 +1,14 @@ +package win32 + +import "core:strings"; + +foreign { + @(link_name="_wgetcwd") _get_cwd_wide :: proc(buffer: Wstring, buf_len: int) -> ^Wstring --- +} + +get_cwd :: proc(allocator := context.temp_allocator) -> string { + buffer := make([]u16, MAX_PATH_WIDE, allocator); + _get_cwd_wide(Wstring(&buffer[0]), MAX_PATH_WIDE); + file := ucs2_to_utf8(buffer[:], allocator); + return strings.trim_right_null(file); +} \ No newline at end of file diff --git a/core/sys/win32/general.odin b/core/sys/win32/general.odin index c34294b51..f4f3de380 100644 --- a/core/sys/win32/general.odin +++ b/core/sys/win32/general.odin @@ -108,6 +108,8 @@ File_Attribute_Data :: struct { file_size_low: u32, } +// NOTE(Jeroen): The widechar version might want at least the 32k MAX_PATH_WIDE +// https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-findfirstfilew#parameters Find_Data_W :: struct{ file_attributes: u32, creation_time: Filetime, @@ -798,6 +800,7 @@ is_key_down :: inline proc(key: Key_Code) -> bool { return get_async_key_state(i MAX_PATH :: 0x00000104; +MAX_PATH_WIDE :: 0x8000; HANDLE_FLAG_INHERIT :: 1; HANDLE_FLAG_PROTECT_FROM_CLOSE :: 2; -- cgit v1.2.3 From 090937f8af95985baf0ffb22630768793a0c91e4 Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Sat, 9 Mar 2019 12:45:17 +0100 Subject: Add convenience functions for open + save dialogs. --- core/sys/win32/comdlg32.odin | 91 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 89 insertions(+), 2 deletions(-) (limited to 'core/sys') diff --git a/core/sys/win32/comdlg32.odin b/core/sys/win32/comdlg32.odin index 790c9d598..54b45886e 100644 --- a/core/sys/win32/comdlg32.odin +++ b/core/sys/win32/comdlg32.odin @@ -2,6 +2,7 @@ package win32 foreign import "system:comdlg32.lib" +import "core:strings" OFN_Hook_Proc :: #type proc "stdcall" (hdlg: Hwnd, msg: u32, wparam: Wparam, lparam: Lparam) -> Uint_Ptr; @@ -61,11 +62,82 @@ Open_File_Name_W :: struct { foreign comdlg32 { @(link_name="GetOpenFileNameA") get_open_file_name_a :: proc(arg1: ^Open_File_Name_A) -> Bool --- @(link_name="GetOpenFileNameW") get_open_file_name_w :: proc(arg1: ^Open_File_Name_W) -> Bool --- - + @(link_name="GetSaveFileNameA") get_save_file_name_a :: proc(arg1: ^Open_File_Name_A) -> Bool --- + @(link_name="GetSaveFileNameW") get_save_file_name_w :: proc(arg1: ^Open_File_Name_W) -> Bool --- @(link_name="CommDlgExtendedError") comm_dlg_extended_error :: proc() -> u32 --- } -OFN_ALLOWMULTISELECT :: 0x00000200; +OPEN_TITLE :: "Select file to open"; +OPEN_FLAGS :: u32(OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST); +OPEN_FLAGS_MULTI :: u32(OPEN_FLAGS | OFN_ALLOWMULTISELECT | OFN_EXPLORER); + +SAVE_TITLE :: "Select file to save"; +SAVE_FLAGS :: u32(OFN_OVERWRITEPROMPT | OFN_EXPLORER); +SAVE_EXT :: "txt"; + +OpenSaveMode :: enum{ + Open = 0, + Save = 1, +} + +_open_file_dialog :: proc(title: string, dir: string, filters: []string, default_filter: u32, flags: u32, default_ext: string, mode: OpenSaveMode, allocator := context.temp_allocator) -> (path: string, ok: bool) { + ok = true; + + file_buf := make([]u16, MAX_PATH_WIDE, allocator); + + // Filters need to be passed as a pair of strings (title, filter) + filter_len := u32(len(filters)); + if filter_len % 2 != 0 do return "", false; + default_filter = clamp(default_filter, 1, filter_len / 2); + + filter := strings.join(filters, "\u0000", context.temp_allocator); + filter = strings.concatenate({filter, "\u0000"}, context.temp_allocator); + filter_w := utf8_to_wstring(filter, context.temp_allocator); + + ofn := Open_File_Name_W{ + struct_size = size_of(Open_File_Name_W), + file = Wstring(&file_buf[0]), + max_file = MAX_PATH_WIDE, + title = utf8_to_wstring(title, context.temp_allocator), + filter = filter_w, + initial_dir = utf8_to_wstring(dir, context.temp_allocator), + filter_index = u32(default_filter), + def_ext = utf8_to_wstring(default_ext, context.temp_allocator), + flags = u32(flags), + }; + + if mode == OpenSaveMode.Open { + ok = bool(get_open_file_name_w(&ofn)); + } else if mode == OpenSaveMode.Save { + ok = bool(get_save_file_name_w(&ofn)); + } else do ok = false; + + if !ok { + delete(file_buf); + return "", false; + } + + file_name := ucs2_to_utf8(file_buf[:], allocator); + path = strings.trim_right_null(file_name); + return; +} + +select_file_to_open :: proc(title := OPEN_TITLE, dir := ".", filters := []string{"All Files", "*.*"}, default_filter := u32(1), flags := OPEN_FLAGS, allocator := context.temp_allocator) -> (path: string, ok: bool) { + + path, ok = _open_file_dialog(title, dir, filters, default_filter, flags, "", OpenSaveMode.Open, allocator); + return; +} + +select_file_to_save :: proc(title := SAVE_TITLE, dir := ".", filters := []string{"All Files", "*.*"}, default_filter := u32(1), flags := SAVE_FLAGS, default_ext := SAVE_EXT, allocator := context.temp_allocator) -> (path: string, ok: bool) { + + path, ok = _open_file_dialog(title, dir, filters, default_filter, flags, default_ext, OpenSaveMode.Save, allocator); + return; +} + +// TODO: Implement convenience function for select_file_to_open with ALLOW_MULTI_SELECT that takes +// it output of the form "path\u0000\file1u\0000file2" and turns it into []string with the path + file pre-concatenated for you. + +OFN_ALLOWMULTISELECT :: 0x00000200; // NOTE(Jeroen): Without OFN_EXPLORER it uses the Win3 dialog. OFN_CREATEPROMPT :: 0x00002000; OFN_DONTADDTORECENT :: 0x02000000; OFN_ENABLEHOOK :: 0x00000020; @@ -91,3 +163,18 @@ OFN_PATHMUSTEXIST :: 0x00000800; OFN_READONLY :: 0x00000001; OFN_SHAREAWARE :: 0x00004000; OFN_SHOWHELP :: 0x00000010; + +CDERR_DIALOGFAILURE :: 0x0000FFFF; +CDERR_GENERALCODES :: 0x00000000; +CDERR_STRUCTSIZE :: 0x00000001; +CDERR_INITIALIZATION :: 0x00000002; +CDERR_NOTEMPLATE :: 0x00000003; +CDERR_NOHINSTANCE :: 0x00000004; +CDERR_LOADSTRFAILURE :: 0x00000005; +CDERR_FINDRESFAILURE :: 0x00000006; +CDERR_LOADRESFAILURE :: 0x00000007; +CDERR_LOCKRESFAILURE :: 0x00000008; +CDERR_MEMALLOCFAILURE :: 0x00000009; +CDERR_MEMLOCKFAILURE :: 0x0000000A; +CDERR_NOHOOK :: 0x0000000B; +CDERR_REGISTERMSGFAIL :: 0x0000000C; \ No newline at end of file -- cgit v1.2.3 From 4f24f1172edcda5094eb6b89deac8613c433c13e Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Sat, 9 Mar 2019 13:48:48 +0100 Subject: Stylistic improvements to new comdlg helpers. --- core/sys/win32/comdlg32.odin | 57 +++++++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 24 deletions(-) (limited to 'core/sys') diff --git a/core/sys/win32/comdlg32.odin b/core/sys/win32/comdlg32.odin index 54b45886e..3d9fb74c4 100644 --- a/core/sys/win32/comdlg32.odin +++ b/core/sys/win32/comdlg32.odin @@ -75,14 +75,15 @@ SAVE_TITLE :: "Select file to save"; SAVE_FLAGS :: u32(OFN_OVERWRITEPROMPT | OFN_EXPLORER); SAVE_EXT :: "txt"; -OpenSaveMode :: enum{ +Open_Save_Mode :: enum { Open = 0, Save = 1, } -_open_file_dialog :: proc(title: string, dir: string, filters: []string, default_filter: u32, flags: u32, default_ext: string, mode: OpenSaveMode, allocator := context.temp_allocator) -> (path: string, ok: bool) { - ok = true; - +_open_file_dialog :: proc(title: string, dir: string, + filters: []string, default_filter: u32, + flags: u32, default_ext: string, + mode: Open_Save_Mode, allocator := context.temp_allocator) -> (path: string, ok: bool = true) { file_buf := make([]u16, MAX_PATH_WIDE, allocator); // Filters need to be passed as a pair of strings (title, filter) @@ -90,28 +91,31 @@ _open_file_dialog :: proc(title: string, dir: string, filters: []string, default if filter_len % 2 != 0 do return "", false; default_filter = clamp(default_filter, 1, filter_len / 2); - filter := strings.join(filters, "\u0000", context.temp_allocator); - filter = strings.concatenate({filter, "\u0000"}, context.temp_allocator); - filter_w := utf8_to_wstring(filter, context.temp_allocator); + filter: string; + filter = strings.join(filters, "\u0000", context.temp_allocator); + filter = strings.concatenate({filter, "\u0000"}, context.temp_allocator); ofn := Open_File_Name_W{ - struct_size = size_of(Open_File_Name_W), - file = Wstring(&file_buf[0]), - max_file = MAX_PATH_WIDE, - title = utf8_to_wstring(title, context.temp_allocator), - filter = filter_w, - initial_dir = utf8_to_wstring(dir, context.temp_allocator), + struct_size = size_of(Open_File_Name_W), + file = Wstring(&file_buf[0]), + max_file = MAX_PATH_WIDE, + title = utf8_to_wstring(title, context.temp_allocator), + filter = utf8_to_wstring(filter, context.temp_allocator), + initial_dir = utf8_to_wstring(dir, context.temp_allocator), filter_index = u32(default_filter), - def_ext = utf8_to_wstring(default_ext, context.temp_allocator), - flags = u32(flags), + def_ext = utf8_to_wstring(default_ext, context.temp_allocator), + flags = u32(flags), }; - if mode == OpenSaveMode.Open { - ok = bool(get_open_file_name_w(&ofn)); - } else if mode == OpenSaveMode.Save { + switch mode { + case .Open: + ok = bool(get_open_file_name_w(&ofn)); + case .Save: ok = bool(get_save_file_name_w(&ofn)); - } else do ok = false; - + case: + ok = false; + } + if !ok { delete(file_buf); return "", false; @@ -122,15 +126,20 @@ _open_file_dialog :: proc(title: string, dir: string, filters: []string, default return; } -select_file_to_open :: proc(title := OPEN_TITLE, dir := ".", filters := []string{"All Files", "*.*"}, default_filter := u32(1), flags := OPEN_FLAGS, allocator := context.temp_allocator) -> (path: string, ok: bool) { +select_file_to_open :: proc(title := OPEN_TITLE, dir := ".", + filters := []string{"All Files", "*.*"}, default_filter := u32(1), + flags := OPEN_FLAGS, allocator := context.temp_allocator) -> (path: string, ok: bool) { - path, ok = _open_file_dialog(title, dir, filters, default_filter, flags, "", OpenSaveMode.Open, allocator); + path, ok = _open_file_dialog(title, dir, filters, default_filter, flags, "", Open_Save_Mode.Open, allocator); return; } -select_file_to_save :: proc(title := SAVE_TITLE, dir := ".", filters := []string{"All Files", "*.*"}, default_filter := u32(1), flags := SAVE_FLAGS, default_ext := SAVE_EXT, allocator := context.temp_allocator) -> (path: string, ok: bool) { +select_file_to_save :: proc(title := SAVE_TITLE, dir := ".", + filters := []string{"All Files", "*.*"}, default_filter := u32(1), + flags := SAVE_FLAGS, default_ext := SAVE_EXT, + allocator := context.temp_allocator) -> (path: string, ok: bool) { - path, ok = _open_file_dialog(title, dir, filters, default_filter, flags, default_ext, OpenSaveMode.Save, allocator); + path, ok = _open_file_dialog(title, dir, filters, default_filter, flags, default_ext, Open_Save_Mode.Save, allocator); return; } -- cgit v1.2.3