mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-02 20:58:15 +00:00
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:
@@ -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),
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
@@ -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]
|
||||
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 }
|
||||
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user