Merge remote-tracking branch 'upstream/master' into sys-windows-2

# Conflicts:
#	core/sys/windows/kernel32.odin
#	core/sys/windows/types.odin
#	core/sys/windows/user32.odin
#	core/sys/windows/winerror.odin
This commit is contained in:
Thomas la Cour
2024-07-11 21:20:53 +02:00
343 changed files with 36936 additions and 9191 deletions
+1 -1
View File
@@ -192,7 +192,7 @@ StringCopyToOdinString :: proc(
max := StringGetMaximumSizeForEncoding(length, StringEncoding(StringBuiltInEncodings.UTF8))
buf, err := make([]byte, max, allocator)
if err != nil do return
if err != nil { return }
raw_str := runtime.Raw_String {
data = raw_data(buf),
+4
View File
@@ -712,3 +712,7 @@ Window_setDelegate :: proc "c" (self: ^Window, delegate: ^WindowDelegate) {
Window_backingScaleFactor :: proc "c" (self: ^Window) -> Float {
return msgSend(Float, self, "backingScaleFactor")
}
@(objc_type=Window, objc_name="setWantsLayer")
Window_setWantsLayer :: proc "c" (self: ^Window, ok: BOOL) {
msgSend(nil, self, "setWantsLayer:", ok)
}
@@ -3,6 +3,10 @@ package darwin
import "core:c"
import "base:runtime"
// IMPORTANT NOTE: direct syscall usage is not allowed by Apple's review process of apps and should
// be entirely avoided in the builtin Odin collections, these are here for users if they don't
// care about the Apple review process.
// this package uses the sys prefix for the proc names to indicate that these aren't native syscalls but directly call such
sys_write_string :: proc (fd: c.int, message: string) -> bool {
return syscall_write(fd, raw_data(message), cast(u64)len(message))
File diff suppressed because it is too large Load Diff
@@ -3,6 +3,10 @@ package darwin
import "core:c"
import "base:intrinsics"
// IMPORTANT NOTE: direct syscall usage is not allowed by Apple's review process of apps and should
// be entirely avoided in the builtin Odin collections, these are here for users if they don't
// care about the Apple review process.
/* flock */
LOCK_SH :: 1 /* shared lock */
LOCK_EX :: 2 /* exclusive lock */
+1 -1
View File
@@ -7,7 +7,7 @@ init_cpu_features :: proc "contextless" () {
@(static) features: CPU_Features
defer cpu_features = features
try_set :: proc "contextless" (name: string, feature: CPU_Feature) -> (ok: bool) {
try_set :: proc "contextless" (name: cstring, feature: CPU_Feature) -> (ok: bool) {
support: b32
if ok = unix.sysctlbyname(name, &support); ok && support {
features += { feature }
+1 -1
View File
@@ -117,7 +117,7 @@ init_cpu_name :: proc "c" () {
return
}
_buf := transmute(^[0x12]u32)&_cpu_name_buf
_buf := (^[0x12]u32)(&_cpu_name_buf)
_buf[ 0], _buf[ 1], _buf[ 2], _buf[ 3] = cpuid(0x8000_0002, 0)
_buf[ 4], _buf[ 5], _buf[ 6], _buf[ 7] = cpuid(0x8000_0003, 0)
_buf[ 8], _buf[ 9], _buf[10], _buf[11] = cpuid(0x8000_0004, 0)
+1 -1
View File
@@ -12,7 +12,7 @@ version_string_buf: [1024]u8
init_os_version :: proc () {
os_version.platform = .FreeBSD
kernel_version_buf: [129]u8
kernel_version_buf: [1024]u8
b := strings.builder_from_bytes(version_string_buf[:])
// Retrieve kernel info using `sysctl`, e.g. FreeBSD 13.1-RELEASE-p2 GENERIC
+86 -49
View File
@@ -48,6 +48,7 @@ Errno :: enum i32 {
ENOSYS = 38,
ENOTEMPTY = 39,
ELOOP = 40,
EUNKNOWN_41 = 41,
ENOMSG = 42,
EIDRM = 43,
ECHRNG = 44,
@@ -64,6 +65,7 @@ Errno :: enum i32 {
ENOANO = 55,
EBADRQC = 56,
EBADSLT = 57,
EUNKNOWN_58 = 58,
EBFONT = 59,
ENOSTR = 60,
ENODATA = 61,
@@ -150,44 +152,66 @@ Errno :: enum i32 {
RDONLY flag is not present, because it has the value of 0, i.e. it is the
default, unless WRONLY or RDWR is specified.
*/
Open_Flags_Bits :: enum {
WRONLY = 0,
RDWR = 1,
CREAT = 6,
EXCL = 7,
NOCTTY = 8,
TRUNC = 9,
APPEND = 10,
NONBLOCK = 11,
DSYNC = 12,
ASYNC = 13,
DIRECT = 14,
LARGEFILE = 15,
DIRECTORY = 16,
NOFOLLOW = 17,
NOATIME = 18,
CLOEXEC = 19,
PATH = 21,
}
when ODIN_ARCH != .arm64 && ODIN_ARCH != .arm32 {
Open_Flags_Bits :: enum {
WRONLY = 0,
RDWR = 1,
CREAT = 6,
EXCL = 7,
NOCTTY = 8,
TRUNC = 9,
APPEND = 10,
NONBLOCK = 11,
DSYNC = 12,
ASYNC = 13,
DIRECT = 14,
LARGEFILE = 15,
DIRECTORY = 16,
NOFOLLOW = 17,
NOATIME = 18,
CLOEXEC = 19,
PATH = 21,
}
// https://github.com/torvalds/linux/blob/7367539ad4b0f8f9b396baf02110962333719a48/include/uapi/asm-generic/fcntl.h#L19
#assert(1 << uint(Open_Flags_Bits.WRONLY) == 0o0000000_1)
#assert(1 << uint(Open_Flags_Bits.RDWR) == 0o0000000_2)
#assert(1 << uint(Open_Flags_Bits.CREAT) == 0o00000_100)
#assert(1 << uint(Open_Flags_Bits.EXCL) == 0o00000_200)
#assert(1 << uint(Open_Flags_Bits.NOCTTY) == 0o00000_400)
#assert(1 << uint(Open_Flags_Bits.TRUNC) == 0o0000_1000)
#assert(1 << uint(Open_Flags_Bits.APPEND) == 0o0000_2000)
#assert(1 << uint(Open_Flags_Bits.NONBLOCK) == 0o0000_4000)
#assert(1 << uint(Open_Flags_Bits.DSYNC) == 0o000_10000)
#assert(1 << uint(Open_Flags_Bits.ASYNC) == 0o000_20000)
#assert(1 << uint(Open_Flags_Bits.DIRECT) == 0o000_40000)
#assert(1 << uint(Open_Flags_Bits.LARGEFILE) == 0o00_100000)
#assert(1 << uint(Open_Flags_Bits.DIRECTORY) == 0o00_200000)
#assert(1 << uint(Open_Flags_Bits.NOFOLLOW) == 0o00_400000)
#assert(1 << uint(Open_Flags_Bits.NOATIME) == 0o0_1000000)
#assert(1 << uint(Open_Flags_Bits.CLOEXEC) == 0o0_2000000)
#assert(1 << uint(Open_Flags_Bits.PATH) == 0o_10000000)
// https://github.com/torvalds/linux/blob/7367539ad4b0f8f9b396baf02110962333719a48/include/uapi/asm-generic/fcntl.h#L19
#assert(1 << uint(Open_Flags_Bits.WRONLY) == 0o0000000_1)
#assert(1 << uint(Open_Flags_Bits.RDWR) == 0o0000000_2)
#assert(1 << uint(Open_Flags_Bits.CREAT) == 0o00000_100)
#assert(1 << uint(Open_Flags_Bits.EXCL) == 0o00000_200)
#assert(1 << uint(Open_Flags_Bits.NOCTTY) == 0o00000_400)
#assert(1 << uint(Open_Flags_Bits.TRUNC) == 0o0000_1000)
#assert(1 << uint(Open_Flags_Bits.APPEND) == 0o0000_2000)
#assert(1 << uint(Open_Flags_Bits.NONBLOCK) == 0o0000_4000)
#assert(1 << uint(Open_Flags_Bits.DSYNC) == 0o000_10000)
#assert(1 << uint(Open_Flags_Bits.ASYNC) == 0o000_20000)
#assert(1 << uint(Open_Flags_Bits.DIRECT) == 0o000_40000)
#assert(1 << uint(Open_Flags_Bits.LARGEFILE) == 0o00_100000)
#assert(1 << uint(Open_Flags_Bits.DIRECTORY) == 0o00_200000)
#assert(1 << uint(Open_Flags_Bits.NOFOLLOW) == 0o00_400000)
#assert(1 << uint(Open_Flags_Bits.NOATIME) == 0o0_1000000)
#assert(1 << uint(Open_Flags_Bits.CLOEXEC) == 0o0_2000000)
#assert(1 << uint(Open_Flags_Bits.PATH) == 0o_10000000)
} else {
Open_Flags_Bits :: enum {
WRONLY = 0,
RDWR = 1,
CREAT = 6,
EXCL = 7,
NOCTTY = 8,
TRUNC = 9,
APPEND = 10,
NONBLOCK = 11,
DSYNC = 12,
ASYNC = 13,
DIRECTORY = 14,
NOFOLLOW = 15,
DIRECT = 16,
LARGEFILE = 17,
NOATIME = 18,
CLOEXEC = 19,
PATH = 21,
}
}
/*
Bits for FD_Flags bitset
@@ -867,7 +891,7 @@ Wait_Option :: enum {
WSTOPPED = 1,
WEXITED = 2,
WCONTINUED = 3,
WNOWAIT = 24,
WNOWAIT = 24,
// // For processes created using clone
__WNOTHREAD = 29,
__WALL = 30,
@@ -946,9 +970,22 @@ Sig_Stack_Flag :: enum i32 {
AUTODISARM = 31,
}
Sig_Action_Flag :: enum u32 {
NOCLDSTOP = 0,
NOCLDWAIT = 1,
SIGINFO = 2,
UNSUPPORTED = 10,
EXPOSE_TAGBITS = 11,
RESTORER = 26,
ONSTACK = 27,
RESTART = 28,
NODEFER = 30,
RESETHAND = 31,
}
/*
Type of socket to create
- For TCP you want to use SOCK_STREAM
- For TCP you want to use SOCK_STREAM
- For UDP you want to use SOCK_DGRAM
Also see `Protocol`
*/
@@ -1427,16 +1464,16 @@ Futex_Flags_Bits :: enum {
Kind of operation on futex, see FUTEX_WAKE_OP
*/
Futex_Arg_Op :: enum {
SET = 0, /* uaddr2 = oparg; */
ADD = 1, /* uaddr2 += oparg; */
OR = 2, /* uaddr2 |= oparg; */
ANDN = 3, /* uaddr2 &= ~oparg; */
XOR = 4, /* uaddr2 ^= oparg; */
PO2_SET = 0, /* uaddr2 = 1<<oparg; */
PO2_ADD = 1, /* uaddr2 += 1<<oparg; */
PO2_OR = 2, /* uaddr2 |= 1<<oparg; */
PO2_ANDN = 3, /* uaddr2 &= ~(1<<oparg); */
PO2_XOR = 4, /* uaddr2 ^= 1<<oparg; */
SET = 0, /* uaddr2 = oparg */
ADD = 1, /* uaddr2 += oparg */
OR = 2, /* uaddr2 |= oparg */
ANDN = 3, /* uaddr2 &= ~oparg */
XOR = 4, /* uaddr2 ^= oparg */
PO2_SET = 0, /* uaddr2 = 1<<oparg */
PO2_ADD = 1, /* uaddr2 += 1<<oparg */
PO2_OR = 2, /* uaddr2 |= 1<<oparg */
PO2_ANDN = 3, /* uaddr2 &~= 1<<oparg */
PO2_XOR = 4, /* uaddr2 ^= 1<<oparg */
}
/*
+39 -29
View File
@@ -69,7 +69,7 @@ close :: proc "contextless" (fd: Fd) -> (Errno) {
stat :: proc "contextless" (filename: cstring, stat: ^Stat) -> (Errno) {
when size_of(int) == 8 {
when ODIN_ARCH == .arm64 {
ret := syscall(SYS_fstatat, AT_FDCWD, cast(rawptr) filename, stat)
ret := syscall(SYS_fstatat, AT_FDCWD, cast(rawptr) filename, stat, 0)
return Errno(-ret)
} else {
ret := syscall(SYS_stat, cast(rawptr) filename, stat)
@@ -200,10 +200,25 @@ brk :: proc "contextless" (addr: uintptr) -> (Errno) {
return Errno(-ret)
}
/*
Returns from signal handlers on some archs.
*/
rt_sigreturn :: proc "c" () -> ! {
intrinsics.syscall(uintptr(SYS_rt_sigreturn))
unreachable()
}
/*
Alter an action taken by a process.
*/
rt_sigaction :: proc "contextless" (sig: Signal, sigaction: ^Sig_Action, old_sigaction: ^Sig_Action) -> Errno {
rt_sigaction :: proc "contextless" (sig: Signal, sigaction: ^Sig_Action($T), old_sigaction: ^Sig_Action) -> Errno {
// NOTE(jason): It appears that the restorer is required for i386 and amd64
when ODIN_ARCH == .i386 || ODIN_ARCH == .amd64 {
sigaction.flags += {.RESTORER}
}
if sigaction != nil && sigaction.restorer == nil && .RESTORER in sigaction.flags {
sigaction.restorer = rt_sigreturn
}
ret := syscall(SYS_rt_sigaction, sig, sigaction, old_sigaction, size_of(Sig_Set))
return Errno(-ret)
}
@@ -1123,7 +1138,7 @@ ftruncate :: proc "contextless" (fd: Fd, length: i64) -> (Errno) {
ret := syscall(SYS_ftruncate64, fd, compat64_arg_pair(length))
return Errno(-ret)
} else {
ret := syscall(SYS_truncate, fd, compat64_arg_pair(length))
ret := syscall(SYS_ftruncate, fd, compat64_arg_pair(length))
return Errno(-ret)
}
}
@@ -1231,7 +1246,7 @@ creat :: proc "contextless" (name: cstring, mode: Mode) -> (Fd, Errno) {
*/
link :: proc "contextless" (target: cstring, linkpath: cstring) -> (Errno) {
when ODIN_ARCH == .arm64 {
ret := syscall(SYS_linkat, AT_FDCWD, cast(rawptr) target, AT_FDCWD, cast(rawptr) linkpath)
ret := syscall(SYS_linkat, AT_FDCWD, cast(rawptr) target, AT_FDCWD, cast(rawptr) linkpath, 0)
return Errno(-ret)
} else {
ret := syscall(SYS_link, cast(rawptr) target, cast(rawptr) linkpath)
@@ -1261,7 +1276,7 @@ unlink :: proc "contextless" (name: cstring) -> (Errno) {
*/
symlink :: proc "contextless" (target: cstring, linkpath: cstring) -> (Errno) {
when ODIN_ARCH == .arm64 {
ret := syscall(SYS_symlinkat, AT_FDCWD, cast(rawptr) target, cast(rawptr) linkpath)
ret := syscall(SYS_symlinkat, cast(rawptr) target, AT_FDCWD, cast(rawptr) linkpath)
return Errno(-ret)
} else {
ret := syscall(SYS_symlink, cast(rawptr) target, cast(rawptr) linkpath)
@@ -1291,7 +1306,7 @@ readlink :: proc "contextless" (name: cstring, buf: []u8) -> (int, Errno) {
*/
chmod :: proc "contextless" (name: cstring, mode: Mode) -> (Errno) {
when ODIN_ARCH == .arm64 {
ret := syscall(SYS_fchmodat, cast(rawptr) name, transmute(u32) mode, 0)
ret := syscall(SYS_fchmodat, AT_FDCWD, cast(rawptr) name, transmute(u32) mode)
return Errno(-ret)
} else {
ret := syscall(SYS_chmod, cast(rawptr) name, transmute(u32) mode)
@@ -1718,9 +1733,9 @@ getpgrp :: proc "contextless" () -> (Pid, Errno) {
Create a session and set the process group ID.
Available since Linux 2.0.
*/
setsid :: proc "contextless" () -> (Errno) {
setsid :: proc "contextless" () -> (Pid, Errno) {
ret := syscall(SYS_setsid)
return Errno(-ret)
return errno_unwrap(ret, Pid)
}
/*
@@ -2226,8 +2241,7 @@ futex_wake :: proc "contextless" (futex: ^Futex, op: Futex_Wake_Type, flags: Fut
Returns the total number of waiters that have been woken up plus the number of waiters requeued.
*/
futex_cmp_requeue :: proc "contextless" (futex: ^Futex, op: Futex_Cmp_Requeue_Type, flags: Futex_Flags, requeue_threshold: u32,
requeue_max: i32, requeue_futex: ^Futex, val: i32) -> (int, Errno)
{
requeue_max: i32, requeue_futex: ^Futex, val: i32) -> (int, Errno) {
futex_flags := cast(u32) op + transmute(u32) flags
ret := syscall(SYS_futex, futex, futex_flags, requeue_threshold, requeue_max, requeue_futex, val)
return errno_unwrap(ret, int)
@@ -2238,8 +2252,7 @@ futex_cmp_requeue :: proc "contextless" (futex: ^Futex, op: Futex_Cmp_Requeue_Ty
Returns the total number of waiters that have been woken up.
*/
futex_requeue :: proc "contextless" (futex: ^Futex, op: Futex_Requeue_Type, flags: Futex_Flags, requeue_threshold: u32,
requeue_max: i32, requeue_futex: ^Futex) -> (int, Errno)
{
requeue_max: i32, requeue_futex: ^Futex) -> (int, Errno) {
futex_flags := cast(u32) op + transmute(u32) flags
ret := syscall(SYS_futex, futex, futex_flags, requeue_threshold, requeue_max, requeue_futex)
return errno_unwrap(ret, int)
@@ -2250,8 +2263,7 @@ futex_requeue :: proc "contextless" (futex: ^Futex, op: Futex_Requeue_Type, flag
purpose is to allow implementing conditional values sync primitive, it seems like.
*/
futex_wake_op :: proc "contextless" (futex: ^Futex, op: Futex_Wake_Op_Type, flags: Futex_Flags, wakeup: i32,
dst_wakeup, dst: ^Futex, futex_op: u32) -> (int, Errno)
{
dst_wakeup, dst: ^Futex, futex_op: u32) -> (int, Errno) {
futex_flags := cast(u32) op + transmute(u32) flags
ret := syscall(SYS_futex, futex, futex_flags, wakeup, dst_wakeup, dst, futex_op)
return errno_unwrap(ret, int)
@@ -2261,8 +2273,7 @@ futex_wake_op :: proc "contextless" (futex: ^Futex, op: Futex_Wake_Op_Type, flag
Same as wait, but mask specifies bits that must be equal for the mutex to wake up.
*/
futex_wait_bitset :: proc "contextless" (futex: ^Futex, op: Futex_Wait_Bitset_Type, flags: Futex_Flags, val: u32,
timeout: ^Time_Spec, mask: u32) -> (int, Errno)
{
timeout: ^Time_Spec, mask: u32) -> (int, Errno) {
futex_flags := cast(u32) op + transmute(u32) flags
ret := syscall(SYS_futex, futex, futex_flags, val, timeout, 0, mask)
return errno_unwrap(ret, int)
@@ -2271,8 +2282,7 @@ futex_wait_bitset :: proc "contextless" (futex: ^Futex, op: Futex_Wait_Bitset_Ty
/*
Wake up on bitset.
*/
futex_wake_bitset :: proc "contextless" (futex: ^Futex, op: Futex_Wake_Bitset_Type, flags: Futex_Flags, n_wakeup: u32, mask: u32) -> (int, Errno)
{
futex_wake_bitset :: proc "contextless" (futex: ^Futex, op: Futex_Wake_Bitset_Type, flags: Futex_Flags, n_wakeup: u32, mask: u32) -> (int, Errno) {
futex_flags := cast(u32) op + transmute(u32) flags
ret := syscall(SYS_futex, futex, futex_flags, n_wakeup, 0, 0, mask)
return errno_unwrap(ret, int)
@@ -2280,7 +2290,7 @@ futex_wake_bitset :: proc "contextless" (futex: ^Futex, op: Futex_Wake_Bitset_Ty
// TODO(flysand): Priority inheritance (PI) futicees
futex :: proc {
futex :: proc{
futex_wait,
futex_wake,
futex_cmp_requeue,
@@ -2476,8 +2486,8 @@ tgkill :: proc "contextless" (tgid, tid: Pid, sig: Signal) -> (Errno) {
Wait on process, process group or pid file descriptor.
Available since Linux 2.6.10.
*/
waitid :: proc "contextless" (id_type: Id_Type, id: Id, sig_info: ^Sig_Info, options: Wait_Options) -> (Errno) {
ret := syscall(SYS_waitid, id_type, id, sig_info, transmute(i32) options)
waitid :: proc "contextless" (id_type: Id_Type, id: Id, sig_info: ^Sig_Info, options: Wait_Options, rusage: ^RUsage) -> (Errno) {
ret := syscall(SYS_waitid, id_type, id, sig_info, transmute(i32) options, rusage)
return Errno(-ret)
}
@@ -2504,7 +2514,7 @@ waitid :: proc "contextless" (id_type: Id_Type, id: Id, sig_info: ^Sig_Info, opt
Available since Linux 2.6.16.
*/
openat :: proc "contextless" (fd: Fd, name: cstring, flags: Open_Flags, mode: Mode = {}) -> (Fd, Errno) {
ret := syscall(SYS_openat, fd, AT_FDCWD, transmute(uintptr) name, transmute(u32) mode)
ret := syscall(SYS_openat, fd, transmute(uintptr) name, transmute(u32) flags, transmute(u32) mode)
return errno_unwrap(ret, Fd)
}
@@ -2583,8 +2593,8 @@ linkat :: proc "contextless" (target_dirfd: Fd, oldpath: cstring, link_dirfd: Fd
Create a symbolic link at specified dirfd.
Available since Linux 2.6.16.
*/
symlinkat :: proc "contextless" (dirfd: Fd, target: cstring, linkpath: cstring) -> (Errno) {
ret := syscall(SYS_symlinkat, dirfd, cast(rawptr) target, cast(rawptr) linkpath)
symlinkat :: proc "contextless" (target: cstring, dirfd: Fd, linkpath: cstring) -> (Errno) {
ret := syscall(SYS_symlinkat, cast(rawptr) target, dirfd, cast(rawptr) linkpath)
return Errno(-ret)
}
@@ -2619,13 +2629,13 @@ faccessat :: proc "contextless" (dirfd: Fd, name: cstring, mode: Mode = F_OK) ->
Wait for events on a file descriptor.
Available since Linux 2.6.16.
*/
ppoll :: proc "contextless" (fds: []Poll_Fd, timeout: ^Time_Spec, sigmask: ^Sig_Set) -> (Errno) {
ppoll :: proc "contextless" (fds: []Poll_Fd, timeout: ^Time_Spec, sigmask: ^Sig_Set) -> (i32, Errno) {
when size_of(int) == 8 {
ret := syscall(SYS_ppoll, raw_data(fds), len(fds), timeout, sigmask, size_of(Sig_Set))
return Errno(-ret)
return errno_unwrap(ret, i32)
} else {
ret := syscall(SYS_ppoll_time64, raw_data(fds), len(fds), timeout, sigmask, size_of(Sig_Set))
return Errno(-ret)
return errno_unwrap(ret, i32)
}
}
@@ -2808,8 +2818,8 @@ getrandom :: proc "contextless" (buf: []u8, flags: Get_Random_Flags) -> (int, Er
Execute program relative to a directory file descriptor.
Available since Linux 3.19.
*/
execveat :: proc "contextless" (dirfd: Fd, name: cstring, argv: [^]cstring, envp: [^]cstring) -> (Errno) {
ret := syscall(SYS_execveat, dirfd, cast(rawptr) name, cast(rawptr) argv, cast(rawptr) envp)
execveat :: proc "contextless" (dirfd: Fd, name: cstring, argv: [^]cstring, envp: [^]cstring, flags: FD_Flags = {}) -> (Errno) {
ret := syscall(SYS_execveat, dirfd, cast(rawptr) name, cast(rawptr) argv, cast(rawptr) envp, transmute(i32) flags)
return Errno(-ret)
}
+76 -20
View File
@@ -18,7 +18,7 @@ Gid :: distinct u32
/*
Type for Process IDs, Thread IDs, Thread group ID.
*/
Pid :: distinct int
Pid :: distinct i32
/*
Type for any of: pid, pidfd, pgid.
@@ -89,11 +89,11 @@ FD_Flags :: bit_set[FD_Flags_Bits; i32]
Represents file's permission and status bits
**Example:**
When you're passing a value of this type the recommended usage is:
```
linux.Mode{.S_IXOTH, .S_IROTH} | linux.S_IRWXU | linux.S_IRWXG
```
This would generate a mode that has full permissions for the
file's owner and group, and only "read" and "execute" bits
for others.
@@ -151,9 +151,9 @@ when ODIN_ARCH == .amd64 {
size: i64,
blksize: uint,
blocks: u64,
atim: Time_Spec,
mtim: Time_Spec,
ctim: Time_Spec,
atime: Time_Spec,
mtime: Time_Spec,
ctime: Time_Spec,
ino: Inode,
}
}
@@ -495,16 +495,15 @@ Pid_FD_Flags :: bit_set[Pid_FD_Flags_Bits; i32]
// 1. Odin's bitfields start from 0, whereas signals start from 1
// 2. It's unclear how bitfields act in terms of ABI (are they an array of ints or an array of longs?).
// it makes a difference because ARM is big endian.
@private _SIGSET_NWORDS :: (1024 / (8 * size_of(uint)))
@private _SIGSET_NWORDS :: (8 / size_of(uint))
Sig_Set :: [_SIGSET_NWORDS]uint
@private SI_MAX_SIZE :: 128
@private SI_ARCH_PREAMBLE :: 3 * size_of(i32)
@private SI_PAD_SIZE :: (SI_MAX_SIZE - SI_ARCH_PREAMBLE) / size_of(i32)
@private SI_TIMER_PAD_SIZE :: size_of(Uid) - size_of(i32)
@private SI_ARCH_PREAMBLE :: 4 * size_of(i32)
@private SI_PAD_SIZE :: SI_MAX_SIZE - SI_ARCH_PREAMBLE
Sig_Handler_Fn :: #type proc "c" (sig: Signal)
Sig_Restore_Fn :: #type proc "c" ()
Sig_Restore_Fn :: #type proc "c" () -> !
Sig_Info :: struct #packed {
signo: Signal,
@@ -518,8 +517,9 @@ Sig_Info :: struct #packed {
uid: Uid, /* sender's uid */
},
using _timer: struct {
timerid: i32, /* timer id */
timerid: i32, /* timer id */
overrun: i32, /* overrun count */
value: Sig_Val, /* timer value */
},
/* POSIX.1b signals */
using _rt: struct {
@@ -528,8 +528,8 @@ Sig_Info :: struct #packed {
},
/* SIGCHLD */
using _sigchld: struct {
_pid1: Pid, /* which child */
_uid1: Uid, /* sender's uid */
_pid1: Pid, /* which child */
_uid1: Uid, /* sender's uid */
status: i32, /* exit code */
utime: uint,
stime: uint, //clock_t
@@ -537,7 +537,24 @@ Sig_Info :: struct #packed {
/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
using _sigfault: struct {
addr: rawptr, /* faulting insn/memory ref. */
addr_lsb: i16, /* LSB of the reported address */
using _: struct #raw_union {
trapno: i32, /* Trap number that caused signal */
addr_lsb: i16, /* LSB of the reported address */
using _addr_bnd: struct {
_pad2: u64,
lower: rawptr, /* lower bound during fault */
upper: rawptr, /* upper bound during fault */
},
using _addr_pkey: struct {
_pad3: u64,
pkey: u32, /* protection key on PTE that faulted */
},
using _perf: struct {
perf_data: u64,
perf_type: u32,
perf_flags: u32,
},
},
},
/* SIGPOLL */
using _sigpoll: struct {
@@ -547,12 +564,43 @@ Sig_Info :: struct #packed {
/* SIGSYS */
using _sigsys: struct {
call_addr: rawptr, /* calling user insn */
syscall: i32, /* triggering system call number */
arch: u32, /* AUDIT_ARCH_* of syscall */
syscall: i32, /* triggering system call number */
arch: u32, /* AUDIT_ARCH_* of syscall */
},
},
}
#assert(size_of(Sig_Info) == 128)
when ODIN_ARCH == .amd64 || ODIN_ARCH == .arm64 {
#assert(offset_of(Sig_Info, signo) == 0x00)
#assert(offset_of(Sig_Info, errno) == 0x04)
#assert(offset_of(Sig_Info, code) == 0x08)
#assert(offset_of(Sig_Info, pid) == 0x10)
#assert(offset_of(Sig_Info, uid) == 0x14)
#assert(offset_of(Sig_Info, timerid) == 0x10)
#assert(offset_of(Sig_Info, overrun) == 0x14)
#assert(offset_of(Sig_Info, value) == 0x18)
#assert(offset_of(Sig_Info, status) == 0x18)
#assert(offset_of(Sig_Info, utime) == 0x20)
#assert(offset_of(Sig_Info, stime) == 0x28)
#assert(offset_of(Sig_Info, addr) == 0x10)
#assert(offset_of(Sig_Info, addr_lsb) == 0x18)
#assert(offset_of(Sig_Info, trapno) == 0x18)
#assert(offset_of(Sig_Info, lower) == 0x20)
#assert(offset_of(Sig_Info, upper) == 0x28)
#assert(offset_of(Sig_Info, pkey) == 0x20)
#assert(offset_of(Sig_Info, perf_data) == 0x18)
#assert(offset_of(Sig_Info, perf_type) == 0x20)
#assert(offset_of(Sig_Info, perf_flags) == 0x24)
#assert(offset_of(Sig_Info, band) == 0x10)
#assert(offset_of(Sig_Info, fd) == 0x18)
#assert(offset_of(Sig_Info, call_addr) == 0x10)
#assert(offset_of(Sig_Info, syscall) == 0x18)
#assert(offset_of(Sig_Info, arch) == 0x1C)
} else {
// TODO
}
SIGEV_MAX_SIZE :: 64
SIGEV_PAD_SIZE :: ((SIGEV_MAX_SIZE-size_of(i32)*2+size_of(Sig_Val))/size_of(i32))
@@ -583,12 +631,20 @@ Sig_Stack :: struct {
size: uintptr,
}
Sig_Action_Special :: enum uint {
SIG_DFL = 0,
SIG_IGN = 1,
SIG_ERR = ~uint(0),
}
Sig_Action_Flags :: bit_set[Sig_Action_Flag; uint]
Sig_Action :: struct($T: typeid) {
using _u: struct #raw_union {
handler: Sig_Handler_Fn,
sigaction: #type proc "c" (sig: Signal, si: ^Sig_Info, ctx: ^T),
special: Sig_Action_Special,
},
flags: uint,
flags: Sig_Action_Flags,
restorer: Sig_Restore_Fn,
mask: Sig_Set,
}
@@ -733,7 +789,7 @@ RLimit :: struct {
/*
Structure representing how much of each resource got used.
*/
*/
RUsage :: struct {
utime: Time_Val,
stime: Time_Val,
@@ -813,7 +869,7 @@ when size_of(int) == 8 || ODIN_ARCH == .i386 {
cpid: Pid,
lpid: Pid,
nattach: uint,
_: [2]uint,
_: [2]uint,
}
}
+4 -5
View File
@@ -48,7 +48,7 @@ WCOREDUMP :: #force_inline proc "contextless" (s: u32) -> bool {
return 1 << ((cast(uint)(sig) - 1) % (8*size_of(uint)))
}
@private _sigword :: proc "contextless" (sig: Signal) -> (uint) {
return (cast(uint)sig - 1) / (8*size_of(uint))
return (cast(uint)sig - 1) / (8*size_of(uint))
}
// TODO: sigaddset etc
@@ -85,13 +85,13 @@ dirent_iterate_buf :: proc "contextless" (buf: []u8, offs: ^int) -> (d: ^Dirent,
/// Obtain the name of dirent as a string
/// The lifetime of the string is bound to the lifetime of the provided dirent structure
dirent_name :: proc "contextless" (dirent: ^Dirent) -> string #no_bounds_check {
str := transmute([^]u8) &dirent.name
str := ([^]u8)(&dirent.name)
// Note(flysand): The string size calculated above applies only to the ideal case
// we subtract 1 byte from the string size, because a null terminator is guaranteed
// to be present. But! That said, the dirents are aligned to 8 bytes and the padding
// between the null terminator and the start of the next struct may be not initialized
// which means we also have to scan these garbage bytes.
str_size := (cast(int) dirent.reclen) - 1 - cast(int) offset_of(Dirent, name)
str_size := int(dirent.reclen) - 1 - cast(int)offset_of(Dirent, name)
// This skips *only* over the garbage, since if we're not garbage we're at nul terminator,
// which skips this loop
for str[str_size] != 0 {
@@ -115,7 +115,6 @@ futex_op :: proc "contextless" (arg_op: Futex_Arg_Op, cmp_op: Futex_Cmp_Op, op_a
/// Helper function for constructing the config for caches
perf_cache_config :: #force_inline proc "contextless" (id: Perf_Hardware_Cache_Id,
op: Perf_Hardware_Cache_Op_Id,
res: Perf_Hardware_Cache_Result_Id) -> u64
{
res: Perf_Hardware_Cache_Result_Id) -> u64 {
return u64(id) | (u64(op) << 8) | (u64(res) << 16)
}
+47 -16
View File
@@ -3,29 +3,60 @@ package unix
import "base:intrinsics"
import "core:c"
import "core:sys/darwin"
_ :: darwin
sysctl :: proc "contextless" (mib: []i32, val: ^$T) -> (ok: bool) {
result_size := c.size_t(size_of(T))
res := darwin.syscall_sysctl(
raw_data(mib), len(mib),
val, &result_size,
nil, 0,
)
return res == 0
result_size := uint(size_of(T))
when ODIN_NO_CRT {
res := darwin.syscall_sysctl(
raw_data(mib), len(mib),
val, &result_size,
nil, 0,
)
return res == 0
} else {
foreign {
@(link_name="sysctl") _sysctl :: proc(
name: [^]i32, namelen: u32,
oldp: rawptr, oldlenp: ^uint,
newp: rawptr, newlen: uint,
) -> i32 ---
}
res := _sysctl(
raw_data(mib), u32(len(mib)),
val, &result_size,
nil, 0,
)
return res == 0
}
}
sysctlbyname :: proc "contextless" (name: string, val: ^$T) -> (ok: bool) {
result_size := c.size_t(size_of(T))
res := darwin.syscall_sysctlbyname(
name,
val, &result_size,
nil, 0,
)
return res == 0
sysctlbyname :: proc "contextless" (name: cstring, val: ^$T) -> (ok: bool) {
result_size := uint(size_of(T))
when ODIN_NO_CRT {
res := darwin.syscall_sysctlbyname(
string(name),
val, &result_size,
nil, 0,
)
return res == 0
} else {
foreign {
@(link_name="sysctlbyname") _sysctlbyname :: proc(
name: cstring,
oldp: rawptr, oldlenp: ^uint,
newp: rawptr, newlen: uint,
) -> i32 ---
}
res := _sysctlbyname(
name,
val, &result_size,
nil, 0,
)
return res == 0
}
}
// See sysctl.h for darwin for details
+4 -3
View File
@@ -5,14 +5,15 @@ import "base:intrinsics"
sysctl :: proc(mib: []i32, val: ^$T) -> (ok: bool) {
mib := mib
result_size := i64(size_of(T))
result_size := u64(size_of(T))
res := intrinsics.syscall(SYS_sysctl,
res: uintptr
res, ok = intrinsics.syscall_bsd(SYS_sysctl,
uintptr(raw_data(mib)), uintptr(len(mib)),
uintptr(val), uintptr(&result_size),
uintptr(0), uintptr(0),
)
return res == 0
return
}
// See /usr/include/sys/sysctl.h for details
+2 -2
View File
@@ -962,7 +962,7 @@ prestat_dir_t :: struct {
}
prestat_t :: struct {
tag: u8,
tag: preopentype_t,
using u: struct {
dir: prestat_dir_t,
},
@@ -1158,7 +1158,7 @@ foreign wasi {
/**
* A buffer into which to write the preopened directory name.
*/
path: string,
path: []byte,
) -> errno_t ---
/**
* Create a directory.
+54 -158
View File
@@ -38,20 +38,36 @@ foreign kernel32 {
lpNumberOfCharsWritten: LPDWORD,
lpReserved: LPVOID) -> BOOL ---
PeekConsoleInputW :: proc(hConsoleInput: HANDLE,
lpBuffer: ^INPUT_RECORD,
nLength: DWORD,
lpNumberOfEventsRead: LPDWORD) -> BOOL ---
ReadConsoleInputW :: proc(hConsoleInput: HANDLE,
lpBuffer: ^INPUT_RECORD,
nLength: DWORD,
lpNumberOfEventsRead: LPDWORD) -> BOOL ---
// https://learn.microsoft.com/en-us/windows/console/getnumberofconsoleinputevents
GetNumberOfConsoleInputEvents :: proc(hConsoleInput: HANDLE, lpcNumberOfEvents: LPDWORD) -> BOOL ---
GetConsoleMode :: proc(hConsoleHandle: HANDLE,
lpMode: LPDWORD) -> BOOL ---
SetConsoleMode :: proc(hConsoleHandle: HANDLE,
dwMode: DWORD) -> BOOL ---
SetConsoleCursorPosition :: proc(hConsoleHandle: HANDLE,
dwCursorPosition: COORD) -> BOOL ---
dwCursorPosition: COORD) -> BOOL ---
SetConsoleTextAttribute :: proc(hConsoleOutput: HANDLE,
wAttributes: WORD) -> BOOL ---
GetConsoleCP :: proc() -> CODEPAGE ---
SetConsoleCP :: proc(wCodePageID: CODEPAGE) -> BOOL ---
GetConsoleOutputCP :: proc() -> CODEPAGE ---
SetConsoleOutputCP :: proc(wCodePageID: CODEPAGE) -> BOOL ---
FlushConsoleInputBuffer :: proc(hConsoleInput: HANDLE) -> BOOL ---
GetFileInformationByHandle :: proc(hFile: HANDLE, lpFileInformation: LPBY_HANDLE_FILE_INFORMATION) -> BOOL ---
SetHandleInformation :: proc(hObject: HANDLE,
dwMask: DWORD,
dwFlags: DWORD) -> BOOL ---
@@ -67,6 +83,7 @@ foreign kernel32 {
RemoveVectoredContinueHandler :: proc(Handle: LPVOID) -> DWORD ---
RaiseException :: proc(dwExceptionCode, dwExceptionFlags, nNumberOfArguments: DWORD, lpArguments: ^ULONG_PTR) -> ! ---
SetUnhandledExceptionFilter :: proc(lpTopLevelExceptionFilter: LPTOP_LEVEL_EXCEPTION_FILTER) -> LPTOP_LEVEL_EXCEPTION_FILTER ---
CreateHardLinkW :: proc(lpSymlinkFileName: LPCWSTR,
lpTargetFileName: LPCWSTR,
@@ -87,6 +104,12 @@ foreign kernel32 {
RemoveDirectoryW :: proc(lpPathName: LPCWSTR) -> BOOL ---
SetFileAttributesW :: proc(lpFileName: LPCWSTR, dwFileAttributes: DWORD) -> BOOL ---
SetLastError :: proc(dwErrCode: DWORD) ---
GetCommTimeouts :: proc(handle: HANDLE, timeouts: ^COMMTIMEOUTS) -> BOOL ---
SetCommTimeouts :: proc(handle: HANDLE, timeouts: ^COMMTIMEOUTS) -> BOOL ---
ClearCommError :: proc(hFile: HANDLE, lpErrors: ^Com_Error, lpStat: ^COMSTAT) -> BOOL ---
GetCommState :: proc(handle: HANDLE, dcb: ^DCB) -> BOOL ---
SetCommState :: proc(handle: HANDLE, dcb: ^DCB) -> BOOL ---
GetCommPorts :: proc(lpPortNumbers: PULONG, uPortNumbersCount: ULONG, puPortNumbersFound: PULONG) -> ULONG ---
GetCommandLineW :: proc() -> LPCWSTR ---
GetTempPathW :: proc(nBufferLength: DWORD, lpBuffer: LPCWSTR) -> DWORD ---
GetCurrentProcess :: proc() -> HANDLE ---
@@ -491,6 +514,8 @@ foreign kernel32 {
GetHandleInformation :: proc(hObject: HANDLE, lpdwFlags: ^DWORD) -> BOOL ---
RtlCaptureStackBackTrace :: proc(FramesToSkip: ULONG, FramesToCapture: ULONG, BackTrace: [^]PVOID, BackTraceHash: PULONG) -> USHORT ---
GetSystemPowerStatus :: proc(lpSystemPowerStatus: ^SYSTEM_POWER_STATUS) -> BOOL ---
}
DEBUG_PROCESS :: 0x00000001
@@ -1036,163 +1061,8 @@ foreign kernel32 {
HandlerRoutine :: proc "system" (dwCtrlType: DWORD) -> BOOL
PHANDLER_ROUTINE :: HandlerRoutine
DCB_Config :: struct {
fParity: bool,
fOutxCtsFlow: bool,
fOutxDsrFlow: bool,
fDtrControl: DTR_Control,
fDsrSensitivity: bool,
fTXContinueOnXoff: bool,
fOutX: bool,
fInX: bool,
fErrorChar: bool,
fNull: bool,
fRtsControl: RTS_Control,
fAbortOnError: bool,
BaudRate: DWORD,
ByteSize: BYTE,
Parity: Parity,
StopBits: Stop_Bits,
XonChar: byte,
XoffChar: byte,
ErrorChar: byte,
EvtChar: byte,
}
DTR_Control :: enum byte {
Disable = 0,
Enable = 1,
Handshake = 2,
}
RTS_Control :: enum byte {
Disable = 0,
Enable = 1,
Handshake = 2,
Toggle = 3,
}
Parity :: enum byte {
None = 0,
Odd = 1,
Even = 2,
Mark = 3,
Space = 4,
}
Stop_Bits :: enum byte {
One = 0,
One_And_A_Half = 1,
Two = 2,
}
// A helper procedure to set the values of a DCB structure.
init_dcb_with_config :: proc "contextless" (dcb: ^DCB, config: DCB_Config) {
out: u32
// NOTE(tetra, 2022-09-21): On both Clang 14 on Windows, and MSVC, the bits in the bitfield
// appear to be defined from LSB to MSB order.
// i.e: `fBinary` (the first bitfield in the C source) is the LSB in the `settings` u32.
out |= u32(1) << 0 // fBinary must always be true on Windows.
out |= u32(config.fParity) << 1
out |= u32(config.fOutxCtsFlow) << 2
out |= u32(config.fOutxDsrFlow) << 3
out |= u32(config.fDtrControl) << 4
out |= u32(config.fDsrSensitivity) << 6
out |= u32(config.fTXContinueOnXoff) << 7
out |= u32(config.fOutX) << 8
out |= u32(config.fInX) << 9
out |= u32(config.fErrorChar) << 10
out |= u32(config.fNull) << 11
out |= u32(config.fRtsControl) << 12
out |= u32(config.fAbortOnError) << 14
dcb.settings = out
dcb.BaudRate = config.BaudRate
dcb.ByteSize = config.ByteSize
dcb.Parity = config.Parity
dcb.StopBits = config.StopBits
dcb.XonChar = config.XonChar
dcb.XoffChar = config.XoffChar
dcb.ErrorChar = config.ErrorChar
dcb.EvtChar = config.EvtChar
dcb.DCBlength = size_of(DCB)
}
get_dcb_config :: proc "contextless" (dcb: DCB) -> (config: DCB_Config) {
config.fParity = bool((dcb.settings >> 1) & 0x01)
config.fOutxCtsFlow = bool((dcb.settings >> 2) & 0x01)
config.fOutxDsrFlow = bool((dcb.settings >> 3) & 0x01)
config.fDtrControl = DTR_Control((dcb.settings >> 4) & 0x02)
config.fDsrSensitivity = bool((dcb.settings >> 6) & 0x01)
config.fTXContinueOnXoff = bool((dcb.settings >> 7) & 0x01)
config.fOutX = bool((dcb.settings >> 8) & 0x01)
config.fInX = bool((dcb.settings >> 9) & 0x01)
config.fErrorChar = bool((dcb.settings >> 10) & 0x01)
config.fNull = bool((dcb.settings >> 11) & 0x01)
config.fRtsControl = RTS_Control((dcb.settings >> 12) & 0x02)
config.fAbortOnError = bool((dcb.settings >> 14) & 0x01)
config.BaudRate = dcb.BaudRate
config.ByteSize = dcb.ByteSize
config.Parity = dcb.Parity
config.StopBits = dcb.StopBits
config.XonChar = dcb.XonChar
config.XoffChar = dcb.XoffChar
config.ErrorChar = dcb.ErrorChar
config.EvtChar = dcb.EvtChar
return
}
// NOTE(tetra): See get_dcb_config() and init_dcb_with_config() for help with initializing this.
DCB :: struct {
DCBlength: DWORD, // NOTE(tetra): Must be set to size_of(DCB).
BaudRate: DWORD,
settings: u32, // NOTE(tetra): These are bitfields in the C struct.
wReserved: WORD,
XOnLim: WORD,
XOffLim: WORD,
ByteSize: BYTE,
Parity: Parity,
StopBits: Stop_Bits,
XonChar: byte,
XoffChar: byte,
ErrorChar: byte,
EofChar: byte,
EvtChar: byte,
wReserved1: WORD,
}
@(default_calling_convention="system")
foreign kernel32 {
GetCommState :: proc(handle: HANDLE, dcb: ^DCB) -> BOOL ---
SetCommState :: proc(handle: HANDLE, dcb: ^DCB) -> BOOL ---
}
COMMTIMEOUTS :: struct {
ReadIntervalTimeout: DWORD,
ReadTotalTimeoutMultiplier: DWORD,
ReadTotalTimeoutConstant: DWORD,
WriteTotalTimeoutMultiplier: DWORD,
WriteTotalTimeoutConstant: DWORD,
}
@(default_calling_convention="system")
foreign kernel32 {
GetCommTimeouts :: proc(handle: HANDLE, timeouts: ^COMMTIMEOUTS) -> BOOL ---
SetCommTimeouts :: proc(handle: HANDLE, timeouts: ^COMMTIMEOUTS) -> BOOL ---
}
// NOTE(Jeroen, 2024-06-13): As Odin now supports bit_fields, we no longer need
// a helper procedure. `init_dcb_with_config` and `get_dcb_config` have been removed.
LPFIBER_START_ROUTINE :: #type proc "system" (lpFiberParameter: LPVOID)
@@ -1250,6 +1120,30 @@ SYSTEM_LOGICAL_PROCESSOR_INFORMATION :: struct {
DummyUnion: DUMMYUNIONNAME_u,
}
SYSTEM_POWER_STATUS :: struct {
ACLineStatus: AC_Line_Status,
BatteryFlag: Battery_Flags,
BatteryLifePercent: BYTE,
SystemStatusFlag: BYTE,
BatteryLifeTime: DWORD,
BatteryFullLifeTime: DWORD,
}
AC_Line_Status :: enum BYTE {
Offline = 0,
Online = 1,
Unknown = 255,
}
Battery_Flag :: enum BYTE {
High = 0,
Low = 1,
Critical = 2,
Charging = 3,
No_Battery = 7,
}
Battery_Flags :: bit_set[Battery_Flag; BYTE]
/* Global Memory Flags */
GMEM_FIXED :: 0x0000
GMEM_MOVEABLE :: 0x0002
@@ -1284,3 +1178,5 @@ LOAD_LIBRARY_FLAGS :: enum DWORD {
LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800,
LOAD_LIBRARY_SEARCH_DEFAULT_DIRS = 0x00001000,
}
LPTOP_LEVEL_EXCEPTION_FILTER :: PVECTORED_EXCEPTION_HANDLER
+9 -7
View File
@@ -7,13 +7,13 @@ foreign import "system:Ole32.lib"
/*
typedef enum tagCOINIT
{
COINIT_APARTMENTTHREADED = 0x2, // Apartment model
COINIT_APARTMENTTHREADED = 0x2, // Apartment model
#if (_WIN32_WINNT >= 0x0400 ) || defined(_WIN32_DCOM) // DCOM
// These constants are only valid on Windows NT 4.0
COINIT_MULTITHREADED = COINITBASE_MULTITHREADED,
COINIT_DISABLE_OLE1DDE = 0x4, // Don't use DDE for Ole1 support.
COINIT_SPEED_OVER_MEMORY = 0x8, // Trade memory for speed.
// These constants are only valid on Windows NT 4.0
COINIT_MULTITHREADED = COINITBASE_MULTITHREADED,
COINIT_DISABLE_OLE1DDE = 0x4, // Don't use DDE for Ole1 support.
COINIT_SPEED_OVER_MEMORY = 0x8, // Trade memory for speed.
#endif // DCOM
} COINIT;
*/
@@ -26,9 +26,11 @@ COINIT :: enum DWORD {
}
IUnknown :: struct {
using Vtbl: ^IUnknownVtbl,
using _iunknown_vtable: ^IUnknown_VTable,
}
IUnknownVtbl :: struct {
IUnknownVtbl :: IUnknown_VTable
IUnknown_VTable :: struct {
QueryInterface: proc "system" (This: ^IUnknown, riid: REFIID, ppvObject: ^rawptr) -> HRESULT,
AddRef: proc "system" (This: ^IUnknown) -> ULONG,
Release: proc "system" (This: ^IUnknown) -> ULONG,
+1 -1
View File
@@ -5,7 +5,7 @@ foreign import shell32 "system:Shell32.lib"
@(default_calling_convention="system")
foreign shell32 {
CommandLineToArgvW :: proc(cmd_list: wstring, num_args: ^c_int) -> ^wstring ---
CommandLineToArgvW :: proc(cmd_list: wstring, num_args: ^c_int) -> [^]wstring ---
ShellExecuteW :: proc(
hwnd: HWND,
lpOperation: LPCWSTR,
+101
View File
@@ -0,0 +1,101 @@
//+build windows
package sys_windows
foreign import kernel32 "system:Kernel32.lib"
@(default_calling_convention="system")
foreign kernel32 {
CreateToolhelp32Snapshot :: proc (dwFlags: DWORD, th32ProcessID: DWORD) -> HANDLE ---
Process32FirstW :: proc (hSnapshot: HANDLE, lppe: LPPROCESSENTRY32W) -> BOOL ---
Process32NextW :: proc (hSnapshot: HANDLE, lppe: LPPROCESSENTRY32W) -> BOOL ---
Thread32First :: proc (hSnapshot: HANDLE, lpte: LPTHREADENTRY32) -> BOOL ---
Thread32Next :: proc (hSnapshot: HANDLE, lpte: LPTHREADENTRY32) -> BOOL ---
Module32FirstW :: proc (hSnapshot: HANDLE, lpme: LPMODULEENTRY32W) -> BOOL ---
Module32NextW :: proc (hSnapshot: HANDLE, lpme: LPMODULEENTRY32W) -> BOOL ---
Heap32ListFirst :: proc (hSnapshot: HANDLE, lphl: LPHEAPLIST32) -> BOOL ---
Heap32ListNext :: proc (hSnapshot: HANDLE, lphl: LPHEAPLIST32) -> BOOL ---
Heap32First :: proc (lphe: LPHEAPENTRY32, th32ProcessID: DWORD, th32HeapID: ULONG_PTR) -> BOOL ---
Heap32Next :: proc (lphe: LPHEAPENTRY32) -> BOOL ---
Toolhelp32ReadProcessMemory :: proc (
th32ProcessID: DWORD,
lpBaseAddress: LPCVOID,
lpBuffer: LPVOID,
cbRead: SIZE_T,
lpNumberOfBytesRead: ^SIZE_T,
) -> BOOL ---
}
MAX_MODULE_NAME32 :: 255
TH32CS_INHERIT :: 0x80000000
TH32CS_SNAPHEAPLIST :: 0x00000001
TH32CS_SNAPPROCESS :: 0x00000002
TH32CS_SNAPTHREAD :: 0x00000004
TH32CS_SNAPMODULE :: 0x00000008
TH32CS_SNAPMODULE32 :: 0x00000010
TH32CS_SNAPALL :: TH32CS_SNAPHEAPLIST | TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD | TH32CS_SNAPMODULE
PROCESSENTRY32W :: struct {
dwSize: DWORD,
cntUsage: DWORD,
th32ProcessID: DWORD,
th32DefaultHeapID: ULONG_PTR,
th32ModuleID: DWORD,
cntThreads: DWORD,
th32ParentProcessID: DWORD,
pcPriClassBase: LONG,
dwFlags: DWORD,
szExeFile: [MAX_PATH]WCHAR,
}
LPPROCESSENTRY32W :: ^PROCESSENTRY32W
THREADENTRY32 :: struct {
dwSize: DWORD,
cntUsage: DWORD,
th32ThreadID: DWORD,
th32OwnerProcessID: DWORD,
tpBasePri: LONG,
tpDeltaPri: LONG,
dwFlags: DWORD,
}
LPTHREADENTRY32 :: ^THREADENTRY32
MODULEENTRY32W :: struct {
dwSize: DWORD,
th32ModuleID: DWORD,
th32ProcessID: DWORD,
GlblcntUsage: DWORD,
ProccntUsage: DWORD,
modBaseAddr: ^BYTE,
modBaseSize: DWORD,
hModule: HMODULE,
szModule: [MAX_MODULE_NAME32 + 1]WCHAR,
szExePath: [MAX_PATH]WCHAR,
}
LPMODULEENTRY32W :: ^MODULEENTRY32W
HEAPLIST32 :: struct {
dwSize: SIZE_T,
th32ProcessID: DWORD,
th32HeapID: ULONG_PTR,
dwFlags: DWORD,
}
LPHEAPLIST32 :: ^HEAPLIST32
HEAPENTRY32 :: struct {
dwSize: SIZE_T,
hHandle: HANDLE,
dwAddress: ULONG_PTR,
dwBlockSize: SIZE_T,
dwFlags: DWORD,
dwLockCount: DWORD,
dwResvd: DWORD,
th32ProcessID: DWORD,
th32HeapID: ULONG_PTR,
}
LPHEAPENTRY32 :: ^HEAPENTRY32
+178
View File
@@ -36,6 +36,7 @@ HBITMAP :: distinct HANDLE
HPALETTE :: distinct HANDLE
HGLOBAL :: distinct HANDLE
HHOOK :: distinct HANDLE
HWINEVENTHOOK :: distinct HANDLE
HKEY :: distinct HANDLE
HDESK :: distinct HANDLE
HFONT :: distinct HANDLE
@@ -797,6 +798,14 @@ WNDPROC :: #type proc "system" (HWND, UINT, WPARAM, LPARAM) -> LRESULT
HOOKPROC :: #type proc "system" (code: c_int, wParam: WPARAM, lParam: LPARAM) -> LRESULT
WINEVENTPROC :: #type proc "system" (
hWinEventHook: HWINEVENTHOOK,
event: DWORD,
hwnd: HWND,
idObject, idChild: LONG,
idEventThread, dwmsEventTime: DWORD,
)
CWPRETSTRUCT :: struct {
lResult: LRESULT,
lParam: LPARAM,
@@ -2779,6 +2788,22 @@ OSVERSIONINFOEXW :: struct {
wReserved: UCHAR,
}
LoadLibraryEx_Flag :: enum DWORD {
LOAD_LIBRARY_AS_DATAFILE = 1, // 1 << 1: 0x0002,
LOAD_WITH_ALTERED_SEARCH_PATH = 3, // 1 << 3: 0x0008,
LOAD_IGNORE_CODE_AUTHZ_LEVEL = 4, // 1 << 4: 0x0010,
LOAD_LIBRARY_AS_IMAGE_RESOURCE = 5, // 1 << 5: 0x0020,
LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE = 6, // 1 << 6: 0x0040,
LOAD_LIBRARY_REQUIRE_SIGNED_TARGET = 7, // 1 << 7: 0x0080,
LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR = 8, // 1 << 8: 0x0100,
LOAD_LIBRARY_SEARCH_APPLICATION_DIR = 9, // 1 << 9: 0x0200,
LOAD_LIBRARY_SEARCH_USER_DIRS = 10, // 1 << 10: 0x0400,
LOAD_LIBRARY_SEARCH_SYSTEM32 = 11, // 1 << 11: 0x0800,
LOAD_LIBRARY_SEARCH_DEFAULT_DIRS = 12, // 1 << 12: 0x1000,
LOAD_LIBRARY_SAFE_CURRENT_DIRS = 13, // 1 << 13: 0x2000,
}
LoadLibraryEx_Flags :: distinct bit_set[LoadLibraryEx_Flag]
// https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-quota_limits
// Used in LogonUserExW
PQUOTA_LIMITS :: struct {
@@ -4088,6 +4113,70 @@ CONSOLE_CURSOR_INFO :: struct {
PCONSOLE_SCREEN_BUFFER_INFO :: ^CONSOLE_SCREEN_BUFFER_INFO
PCONSOLE_CURSOR_INFO :: ^CONSOLE_CURSOR_INFO
Event_Type :: enum WORD {
KEY_EVENT = 0x0001,
MOUSE_EVENT = 0x0002,
WINDOW_BUFFER_SIZE_EVENT = 0x0004,
MENU_EVENT = 0x0008,
FOCUS_EVENT = 0x0010,
}
INPUT_RECORD :: struct {
EventType: Event_Type,
Event: struct #raw_union {
KeyEvent: KEY_EVENT_RECORD,
MouseEvent: MOUSE_EVENT_RECORD,
WindowBufferSizeEvent: WINDOW_BUFFER_SIZE_RECORD,
MenuEvent: MENU_EVENT_RECORD,
FocusEvent: FOCUS_EVENT_RECORD,
},
}
Control_Key_State_Bits :: enum {
RIGHT_ALT_PRESSED,
LEFT_ALT_PRESSED,
RIGHT_CTRL_PRESSED,
LEFT_CTRL_PRESSED,
SHIFT_PRESSED,
NUMLOCK_ON,
SCROLLLOCK_ON,
CAPSLOCK_ON,
ENHANCED_KEY,
}
Control_Key_State :: bit_set[Control_Key_State_Bits; DWORD]
KEY_EVENT_RECORD :: struct {
bKeyDown: BOOL,
wRepeatCount: WORD,
wVirtualKeyCode: WORD,
wVirtualScanCode: WORD,
uChar: struct #raw_union {
UnicodeChar: WCHAR,
AsciiChar: CHAR,
},
dwControlKeyState: Control_Key_State,
}
MOUSE_EVENT_RECORD :: struct {
dwMousePosition: COORD,
dwButtonState: DWORD,
dwControlKeyState: DWORD,
dwEventFlags: DWORD,
}
WINDOW_BUFFER_SIZE_RECORD :: struct {
dwSize: COORD,
}
MENU_EVENT_RECORD :: struct {
dwCommandId: UINT,
}
FOCUS_EVENT_RECORD :: struct {
bSetFocus: BOOL,
}
//
// Networking
//
@@ -4326,3 +4415,92 @@ SOCKADDR :: struct {
ENUMRESNAMEPROCW :: #type proc (hModule: HMODULE, lpType: LPCWSTR, lpName: LPWSTR, lParam: LONG_PTR)-> BOOL
ENUMRESTYPEPROCW :: #type proc (hModule: HMODULE, lpType: LPCWSTR, lParam: LONG_PTR)-> BOOL
ENUMRESLANGPROCW :: #type proc (hModule: HMODULE, lpType: LPCWSTR, lpName: LPWSTR, wIDLanguage: LANGID, lParam: LONG_PTR)-> BOOL
DTR_Control :: enum byte {
Disable = 0,
Enable = 1,
Handshake = 2,
}
RTS_Control :: enum byte {
Disable = 0,
Enable = 1,
Handshake = 2,
Toggle = 3,
}
Parity :: enum byte {
None = 0,
Odd = 1,
Even = 2,
Mark = 3,
Space = 4,
}
Stop_Bits :: enum byte {
One = 0,
One_And_A_Half = 1,
Two = 2,
}
DCB :: struct {
DCBlength: DWORD,
BaudRate: DWORD,
using _: bit_field DWORD {
fBinary: bool | 1,
fParity: bool | 1,
fOutxCtsFlow: bool | 1,
fOutxDsrFlow: bool | 1,
fDtrControl: DTR_Control | 2,
fDsrSensitivity: bool | 1,
fTXContinueOnXoff: bool | 1,
fOutX: bool | 1,
fInX: bool | 1,
fErrorChar: bool | 1,
fNull: bool | 1,
fRtsControl: RTS_Control | 2,
fAbortOnError: bool | 1,
},
wReserved: WORD,
XOnLim: WORD,
XOffLim: WORD,
ByteSize: BYTE,
Parity: Parity,
StopBits: Stop_Bits,
XonChar: byte,
XoffChar: byte,
ErrorChar: byte,
EofChar: byte,
EvtChar: byte,
wReserved1: WORD,
}
COMMTIMEOUTS :: struct {
ReadIntervalTimeout: DWORD,
ReadTotalTimeoutMultiplier: DWORD,
ReadTotalTimeoutConstant: DWORD,
WriteTotalTimeoutMultiplier: DWORD,
WriteTotalTimeoutConstant: DWORD,
}
Com_Stat_Bits :: enum {
fCtsHold,
fDsrHold,
fRlsdHold,
fXoffHold,
fXoffSent,
fEof,
fTxim,
}
COMSTAT :: struct {
bits: bit_set[Com_Stat_Bits; DWORD],
cbInQue: DWORD,
cbOutQue: DWORD,
}
Com_Error_Bits :: enum {
RXOVER,
OVERRUN,
RXPARITY,
FRAME,
BREAK,
}
Com_Error :: bit_set[Com_Error_Bits; DWORD]
+20
View File
@@ -17,6 +17,17 @@ foreign user32 {
GetClassNameW :: proc(hWnd: HWND, lpClassName: LPWSTR, nMaxCount: INT) -> INT ---
GetParent :: proc(hWnd: HWND) -> HWND ---
SetWinEventHook :: proc(
eventMin, eventMax: DWORD,
hmodWinEventProc: HMODULE,
pfnWinEvenProc: WINEVENTPROC,
idProcess, idThread: DWORD,
dwFlags: WinEventFlags,
) -> HWINEVENTHOOK ---
IsChild :: proc(hWndParent, hWnd: HWND) -> BOOL ---
RegisterClassW :: proc(lpWndClass: ^WNDCLASSW) -> ATOM ---
RegisterClassExW :: proc(^WNDCLASSEXW) -> ATOM ---
UnregisterClassW :: proc(lpClassName: LPCWSTR, hInstance: HINSTANCE) -> BOOL ---
@@ -703,3 +714,12 @@ DISPLAY_DEVICEW :: struct {
DeviceKey: [128]WCHAR,
}
PDISPLAY_DEVICEW :: ^DISPLAY_DEVICEW
// OUTOFCONTEXT is the zero value, use {}
WinEventFlags :: bit_set[WinEventFlag; DWORD]
WinEventFlag :: enum DWORD {
SKIPOWNTHREAD = 0,
SKIPOWNPROCESS = 1,
INCONTEXT = 2,
}
+2 -2
View File
@@ -110,8 +110,8 @@ utf8_to_utf16 :: proc(s: string, allocator := context.temp_allocator) -> []u16 {
return text[:n]
}
utf8_to_wstring :: proc(s: string, allocator := context.temp_allocator) -> wstring {
if res := utf8_to_utf16(s, allocator); res != nil {
return &res[0]
if res := utf8_to_utf16(s, allocator); len(res) > 0 {
return raw_data(res)
}
return nil
}
+1 -1
View File
@@ -248,7 +248,7 @@ SEVERITY :: enum DWORD {
}
// Generic test for success on any status value (non-negative numbers indicate success).
SUCCEEDED :: #force_inline proc(#any_int result: int) -> bool { return result >= S_OK }
SUCCEEDED :: #force_inline proc "contextless" (#any_int result: int) -> bool { return result >= S_OK }
// and the inverse
FAILED :: #force_inline proc(#any_int result: int) -> bool { return result < S_OK }
+85
View File
@@ -0,0 +1,85 @@
//+build windows
package sys_windows
foreign import kernel32 "system:Kernel32.lib"
@(default_calling_convention="system")
foreign kernel32 {
GetSystemWow64Directory2W :: proc (lpBuffer: LPWSTR, uSize: UINT, ImageFileMachineTyp: WORD) -> UINT ---
GetSystemWow64DirectoryW :: proc (lpBuffer: LPWSTR, uSize: UINT) -> UINT ---
IsWow64GuestMachineSupported :: proc (WowGuestMachine: USHORT, MachineIsSupported: ^BOOL) -> HRESULT ---
IsWow64Process :: proc (hProcess: HANDLE, Wow64Process: PBOOL) -> BOOL ---
IsWow64Process2 :: proc (hProcess: HANDLE, pProcessMachine: ^USHORT, pNativeMachine: ^USHORT) -> BOOL ---
Wow64EnableWow64FsRedirection :: proc (Wow64FsEnableRedirection: BOOLEAN) -> BOOLEAN ---
Wow64DisableWow64FsRedirection :: proc (OldValue: ^PVOID) -> BOOL ---
Wow64RevertWow64FsRedirection :: proc (OlValue: PVOID) -> BOOL ---
Wow64GetThreadContext :: proc (hThread: HANDLE, lpContext: PWOW64_CONTEXT) -> BOOL ---
Wow64SetThreadContext :: proc(hThread: HANDLE, lpContext: ^WOW64_CONTEXT) -> BOOL ---
Wow64SetThreadDefaultGuestMachine :: proc(Machine: USHORT) -> USHORT ---
Wow64SuspendThread :: proc (hThread: HANDLE) -> DWORD ---
}
WOW64_CONTEXT_i386 :: 0x00010000
WOW64_CONTEXT_CONTROL :: (WOW64_CONTEXT_i386 | 0x00000001)
WOW64_CONTEXT_INTEGER :: (WOW64_CONTEXT_i386 | 0x00000002)
WOW64_CONTEXT_SEGMENTS :: (WOW64_CONTEXT_i386 | 0x00000004)
WOW64_CONTEXT_FLOATING_POINT :: (WOW64_CONTEXT_i386 | 0x00000008)
WOW64_CONTEXT_DEBUG_REGISTERS :: (WOW64_CONTEXT_i386 | 0x00000010)
WOW64_CONTEXT_EXTENDED_REGISTERS :: (WOW64_CONTEXT_i386 | 0x00000020)
WOW64_CONTEXT_FULL :: (WOW64_CONTEXT_CONTROL | WOW64_CONTEXT_INTEGER | WOW64_CONTEXT_SEGMENTS)
WOW64_CONTEXT_ALL :: (
WOW64_CONTEXT_CONTROL |
WOW64_CONTEXT_INTEGER |
WOW64_CONTEXT_SEGMENTS |
WOW64_CONTEXT_FLOATING_POINT |
WOW64_CONTEXT_DEBUG_REGISTERS |
WOW64_CONTEXT_EXTENDED_REGISTERS)
WOW64_SIZE_OF_80387_REGISTERS :: 80
WOW64_MAXIMUM_SUPPORTED_EXTENSION :: 512
WOW64_CONTEXT :: struct {
ContextFlags: DWORD,
Dr0: DWORD,
Dr1: DWORD,
Dr2: DWORD,
Dr3: DWORD,
Dr6: DWORD,
Dr7: DWORD,
FloatSave: WOW64_FLOATING_SAVE_AREA,
SegGs: DWORD,
SegFs: DWORD,
SegEs: DWORD,
SegDs: DWORD,
Edi: DWORD,
Esi: DWORD,
Ebx: DWORD,
Edx: DWORD,
Ecx: DWORD,
Eax: DWORD,
Ebp: DWORD,
Eip: DWORD,
SegCs: DWORD,
EFlags: DWORD,
Esp: DWORD,
SegSs: DWORD,
ExtendedRegisters: [WOW64_MAXIMUM_SUPPORTED_EXTENSION]BYTE,
}
PWOW64_CONTEXT :: ^WOW64_CONTEXT
WOW64_FLOATING_SAVE_AREA :: struct {
ControlWord: DWORD,
StatusWord: DWORD,
TagWord: DWORD,
ErrorOffset: DWORD,
ErrorSelector: DWORD,
DataOffset: DWORD,
DataSelector: DWORD,
RegisterArea: [WOW64_SIZE_OF_80387_REGISTERS]BYTE,
Cr0NpxState: DWORD,
}
PWOW64_FLOATING_SAVE_AREA :: ^WOW64_FLOATING_SAVE_AREA