mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-27 16:01:47 -07:00
Merge branch 'master' into json-add-int-key-map-support
This commit is contained in:
@@ -95,11 +95,11 @@ front_ptr :: proc(q: ^$Q/Queue($T)) -> ^T {
|
||||
}
|
||||
|
||||
back :: proc(q: ^$Q/Queue($T)) -> T {
|
||||
idx := (q.offset+uint(q.len))%builtin.len(q.data)
|
||||
idx := (q.offset+uint(q.len - 1))%builtin.len(q.data)
|
||||
return q.data[idx]
|
||||
}
|
||||
back_ptr :: proc(q: ^$Q/Queue($T)) -> ^T {
|
||||
idx := (q.offset+uint(q.len))%builtin.len(q.data)
|
||||
idx := (q.offset+uint(q.len - 1))%builtin.len(q.data)
|
||||
return &q.data[idx]
|
||||
}
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ load_map_from_path :: proc(path: string, allocator: runtime.Allocator, options :
|
||||
data := os.read_entire_file(path, allocator) or_return
|
||||
defer delete(data, allocator)
|
||||
m, err = load_map_from_string(string(data), allocator, options)
|
||||
ok = err != nil
|
||||
ok = err == nil
|
||||
defer if !ok {
|
||||
delete_map(m)
|
||||
}
|
||||
|
||||
@@ -384,6 +384,11 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err:
|
||||
omitempty := false
|
||||
|
||||
json_name, extra := json_name_from_tag_value(reflect.struct_tag_get(reflect.Struct_Tag(info.tags[i]), "json"))
|
||||
|
||||
if json_name == "-" {
|
||||
continue
|
||||
}
|
||||
|
||||
for flag in strings.split_iterator(&extra, ",") {
|
||||
switch flag {
|
||||
case "omitempty":
|
||||
|
||||
@@ -599,6 +599,7 @@ Field_Flag :: enum {
|
||||
Subtype,
|
||||
By_Ptr,
|
||||
No_Broadcast,
|
||||
No_Capture,
|
||||
|
||||
Results,
|
||||
Tags,
|
||||
@@ -619,6 +620,7 @@ field_flag_strings := [Field_Flag]string{
|
||||
.Subtype = "#subtype",
|
||||
.By_Ptr = "#by_ptr",
|
||||
.No_Broadcast = "#no_broadcast",
|
||||
.No_Capture = "#no_capture",
|
||||
|
||||
.Results = "results",
|
||||
.Tags = "field tag",
|
||||
@@ -634,6 +636,7 @@ field_hash_flag_strings := []struct{key: string, flag: Field_Flag}{
|
||||
{"subtype", .Subtype},
|
||||
{"by_ptr", .By_Ptr},
|
||||
{"no_broadcast", .No_Broadcast},
|
||||
{"no_capture", .No_Capture},
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -125,7 +125,7 @@ read_console :: proc(handle: win32.HANDLE, b: []byte) -> (n: int, err: Errno) {
|
||||
src := buf8[:buf8_len]
|
||||
|
||||
ctrl_z := false
|
||||
for i := 0; i < len(src) && n+i < len(b); i += 1 {
|
||||
for i := 0; i < len(src) && n < len(b); i += 1 {
|
||||
x := src[i]
|
||||
if x == 0x1a { // ctrl-z
|
||||
ctrl_z = true
|
||||
|
||||
@@ -22,6 +22,7 @@ General_Error :: enum u32 {
|
||||
Invalid_File,
|
||||
Invalid_Dir,
|
||||
Invalid_Path,
|
||||
Invalid_Callback,
|
||||
|
||||
Pattern_Has_Separator,
|
||||
|
||||
@@ -64,6 +65,7 @@ error_string :: proc(ferr: Error) -> string {
|
||||
case .Invalid_File: return "invalid file"
|
||||
case .Invalid_Dir: return "invalid directory"
|
||||
case .Invalid_Path: return "invalid path"
|
||||
case .Invalid_Callback: return "invalid callback"
|
||||
case .Unsupported: return "unsupported"
|
||||
case .Pattern_Has_Separator: return "pattern has separator"
|
||||
}
|
||||
|
||||
@@ -5,9 +5,9 @@ import "core:time"
|
||||
import "base:runtime"
|
||||
|
||||
File :: struct {
|
||||
impl: _File,
|
||||
impl: rawptr,
|
||||
stream: io.Stream,
|
||||
user_fstat: Fstat_Callback,
|
||||
fstat: Fstat_Callback,
|
||||
}
|
||||
|
||||
File_Mode :: distinct u32
|
||||
|
||||
+59
-55
@@ -6,14 +6,15 @@ import "core:time"
|
||||
import "base:runtime"
|
||||
import "core:sys/linux"
|
||||
|
||||
_File :: struct {
|
||||
File_Impl :: struct {
|
||||
file: File,
|
||||
name: string,
|
||||
fd: linux.Fd,
|
||||
allocator: runtime.Allocator,
|
||||
}
|
||||
|
||||
_stdin : File = {
|
||||
impl = {
|
||||
_stdin := File{
|
||||
impl = &File_Impl{
|
||||
name = "/proc/self/fd/0",
|
||||
fd = 0,
|
||||
allocator = _file_allocator(),
|
||||
@@ -21,9 +22,10 @@ _stdin : File = {
|
||||
stream = {
|
||||
procedure = _file_stream_proc,
|
||||
},
|
||||
fstat = _fstat,
|
||||
}
|
||||
_stdout : File = {
|
||||
impl = {
|
||||
_stdout := File{
|
||||
impl = &File_Impl{
|
||||
name = "/proc/self/fd/1",
|
||||
fd = 1,
|
||||
allocator = _file_allocator(),
|
||||
@@ -31,9 +33,10 @@ _stdout : File = {
|
||||
stream = {
|
||||
procedure = _file_stream_proc,
|
||||
},
|
||||
fstat = _fstat,
|
||||
}
|
||||
_stderr : File = {
|
||||
impl = {
|
||||
_stderr := File{
|
||||
impl = &File_Impl{
|
||||
name = "/proc/self/fd/2",
|
||||
fd = 2,
|
||||
allocator = _file_allocator(),
|
||||
@@ -41,6 +44,7 @@ _stderr : File = {
|
||||
stream = {
|
||||
procedure = _file_stream_proc,
|
||||
},
|
||||
fstat = _fstat,
|
||||
}
|
||||
|
||||
@init
|
||||
@@ -89,40 +93,35 @@ _open :: proc(name: string, flags: File_Flags, perm: File_Mode) -> (f: ^File, er
|
||||
}
|
||||
|
||||
_new_file :: proc(fd: uintptr, _: string = "") -> ^File {
|
||||
file := new(File, file_allocator())
|
||||
_construct_file(file, fd, "")
|
||||
return file
|
||||
}
|
||||
|
||||
_construct_file :: proc(file: ^File, fd: uintptr, _: string = "") {
|
||||
file^ = {
|
||||
impl = {
|
||||
fd = linux.Fd(fd),
|
||||
allocator = file_allocator(),
|
||||
name = _get_full_path(file.impl.fd, file.impl.allocator),
|
||||
},
|
||||
stream = {
|
||||
data = file,
|
||||
procedure = _file_stream_proc,
|
||||
},
|
||||
impl := new(File_Impl, file_allocator())
|
||||
impl.file.impl = impl
|
||||
impl.fd = linux.Fd(fd)
|
||||
impl.allocator = file_allocator()
|
||||
impl.name = _get_full_path(impl.fd, impl.allocator)
|
||||
impl.file.stream = {
|
||||
data = impl,
|
||||
procedure = _file_stream_proc,
|
||||
}
|
||||
impl.file.fstat = _fstat
|
||||
return &impl.file
|
||||
}
|
||||
|
||||
_destroy :: proc(f: ^File) -> Error {
|
||||
_destroy :: proc(f: ^File_Impl) -> Error {
|
||||
if f == nil {
|
||||
return nil
|
||||
}
|
||||
delete(f.impl.name, f.impl.allocator)
|
||||
free(f, f.impl.allocator)
|
||||
a := f.allocator
|
||||
delete(f.name, a)
|
||||
free(f, a)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
_close :: proc(f: ^File) -> Error {
|
||||
if f == nil {
|
||||
_close :: proc(f: ^File_Impl) -> Error {
|
||||
if f == nil{
|
||||
return nil
|
||||
}
|
||||
errno := linux.close(f.impl.fd)
|
||||
errno := linux.close(f.fd)
|
||||
if errno == .EBADF { // avoid possible double free
|
||||
return _get_platform_error(errno)
|
||||
}
|
||||
@@ -131,41 +130,41 @@ _close :: proc(f: ^File) -> Error {
|
||||
}
|
||||
|
||||
_fd :: proc(f: ^File) -> uintptr {
|
||||
if f == nil {
|
||||
if f == nil || f.impl == nil {
|
||||
return ~uintptr(0)
|
||||
}
|
||||
return uintptr(f.impl.fd)
|
||||
impl := (^File_Impl)(f.impl)
|
||||
return uintptr(impl.fd)
|
||||
}
|
||||
|
||||
_name :: proc(f: ^File) -> string {
|
||||
return f.impl.name if f != nil else ""
|
||||
return (^File_Impl)(f.impl).name if f != nil && f.impl != nil else ""
|
||||
}
|
||||
|
||||
_seek :: proc(f: ^File, offset: i64, whence: io.Seek_From) -> (ret: i64, err: Error) {
|
||||
n, errno := linux.lseek(f.impl.fd, offset, linux.Seek_Whence(whence))
|
||||
_seek :: proc(f: ^File_Impl, offset: i64, whence: io.Seek_From) -> (ret: i64, err: Error) {
|
||||
n, errno := linux.lseek(f.fd, offset, linux.Seek_Whence(whence))
|
||||
if errno != .NONE {
|
||||
return -1, _get_platform_error(errno)
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
_read :: proc(f: ^File, p: []byte) -> (i64, Error) {
|
||||
_read :: proc(f: ^File_Impl, p: []byte) -> (i64, Error) {
|
||||
if len(p) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
n, errno := linux.read(f.impl.fd, p[:])
|
||||
n, errno := linux.read(f.fd, p[:])
|
||||
if errno != .NONE {
|
||||
return -1, _get_platform_error(errno)
|
||||
}
|
||||
return i64(n), n == 0 ? io.Error.EOF : nil
|
||||
}
|
||||
|
||||
_read_at :: proc(f: ^File, p: []byte, offset: i64) -> (i64, Error) {
|
||||
_read_at :: proc(f: ^File_Impl, p: []byte, offset: i64) -> (i64, Error) {
|
||||
if offset < 0 {
|
||||
return 0, .Invalid_Offset
|
||||
}
|
||||
|
||||
n, errno := linux.pread(f.impl.fd, p[:], offset)
|
||||
n, errno := linux.pread(f.fd, p[:], offset)
|
||||
if errno != .NONE {
|
||||
return -1, _get_platform_error(errno)
|
||||
}
|
||||
@@ -175,32 +174,31 @@ _read_at :: proc(f: ^File, p: []byte, offset: i64) -> (i64, Error) {
|
||||
return i64(n), nil
|
||||
}
|
||||
|
||||
_write :: proc(f: ^File, p: []byte) -> (i64, Error) {
|
||||
_write :: proc(f: ^File_Impl, p: []byte) -> (i64, Error) {
|
||||
if len(p) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
n, errno := linux.write(f.impl.fd, p[:])
|
||||
n, errno := linux.write(f.fd, p[:])
|
||||
if errno != .NONE {
|
||||
return -1, _get_platform_error(errno)
|
||||
}
|
||||
return i64(n), nil
|
||||
}
|
||||
|
||||
_write_at :: proc(f: ^File, p: []byte, offset: i64) -> (i64, Error) {
|
||||
_write_at :: proc(f: ^File_Impl, p: []byte, offset: i64) -> (i64, Error) {
|
||||
if offset < 0 {
|
||||
return 0, .Invalid_Offset
|
||||
}
|
||||
|
||||
n, errno := linux.pwrite(f.impl.fd, p[:], offset)
|
||||
n, errno := linux.pwrite(f.fd, p[:], offset)
|
||||
if errno != .NONE {
|
||||
return -1, _get_platform_error(errno)
|
||||
}
|
||||
return i64(n), nil
|
||||
}
|
||||
|
||||
_file_size :: proc(f: ^File) -> (n: i64, err: Error) {
|
||||
_file_size :: proc(f: ^File_Impl) -> (n: i64, err: Error) {
|
||||
s: linux.Stat = ---
|
||||
errno := linux.fstat(f.impl.fd, &s)
|
||||
errno := linux.fstat(f.fd, &s)
|
||||
if errno != .NONE {
|
||||
return -1, _get_platform_error(errno)
|
||||
}
|
||||
@@ -208,15 +206,17 @@ _file_size :: proc(f: ^File) -> (n: i64, err: Error) {
|
||||
}
|
||||
|
||||
_sync :: proc(f: ^File) -> Error {
|
||||
return _get_platform_error(linux.fsync(f.impl.fd))
|
||||
impl := (^File_Impl)(f.impl)
|
||||
return _get_platform_error(linux.fsync(impl.fd))
|
||||
}
|
||||
|
||||
_flush :: proc(f: ^File) -> Error {
|
||||
return _get_platform_error(linux.fsync(f.impl.fd))
|
||||
_flush :: proc(f: ^File_Impl) -> Error {
|
||||
return _get_platform_error(linux.fsync(f.fd))
|
||||
}
|
||||
|
||||
_truncate :: proc(f: ^File, size: i64) -> Error {
|
||||
return _get_platform_error(linux.ftruncate(f.impl.fd, size))
|
||||
impl := (^File_Impl)(f.impl)
|
||||
return _get_platform_error(linux.ftruncate(impl.fd, size))
|
||||
}
|
||||
|
||||
_remove :: proc(name: string) -> Error {
|
||||
@@ -292,7 +292,8 @@ _chdir :: proc(name: string) -> Error {
|
||||
}
|
||||
|
||||
_fchdir :: proc(f: ^File) -> Error {
|
||||
return _get_platform_error(linux.fchdir(f.impl.fd))
|
||||
impl := (^File_Impl)(f.impl)
|
||||
return _get_platform_error(linux.fchdir(impl.fd))
|
||||
}
|
||||
|
||||
_chmod :: proc(name: string, mode: File_Mode) -> Error {
|
||||
@@ -302,7 +303,8 @@ _chmod :: proc(name: string, mode: File_Mode) -> Error {
|
||||
}
|
||||
|
||||
_fchmod :: proc(f: ^File, mode: File_Mode) -> Error {
|
||||
return _get_platform_error(linux.fchmod(f.impl.fd, transmute(linux.Mode)(u32(mode))))
|
||||
impl := (^File_Impl)(f.impl)
|
||||
return _get_platform_error(linux.fchmod(impl.fd, transmute(linux.Mode)(u32(mode))))
|
||||
}
|
||||
|
||||
// NOTE: will throw error without super user priviledges
|
||||
@@ -321,7 +323,8 @@ _lchown :: proc(name: string, uid, gid: int) -> Error {
|
||||
|
||||
// NOTE: will throw error without super user priviledges
|
||||
_fchown :: proc(f: ^File, uid, gid: int) -> Error {
|
||||
return _get_platform_error(linux.fchown(f.impl.fd, linux.Uid(uid), linux.Gid(gid)))
|
||||
impl := (^File_Impl)(f.impl)
|
||||
return _get_platform_error(linux.fchown(impl.fd, linux.Uid(uid), linux.Gid(gid)))
|
||||
}
|
||||
|
||||
_chtimes :: proc(name: string, atime, mtime: time.Time) -> Error {
|
||||
@@ -351,7 +354,8 @@ _fchtimes :: proc(f: ^File, atime, mtime: time.Time) -> Error {
|
||||
uint(mtime._nsec) % uint(time.Second),
|
||||
},
|
||||
}
|
||||
return _get_platform_error(linux.utimensat(f.impl.fd, nil, ×[0], nil))
|
||||
impl := (^File_Impl)(f.impl)
|
||||
return _get_platform_error(linux.utimensat(impl.fd, nil, ×[0], nil))
|
||||
}
|
||||
|
||||
_exists :: proc(name: string) -> bool {
|
||||
@@ -443,7 +447,7 @@ _read_entire_pseudo_file_cstring :: proc(name: cstring, allocator: runtime.Alloc
|
||||
|
||||
@(private="package")
|
||||
_file_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) {
|
||||
f := (^File)(stream_data)
|
||||
f := (^File_Impl)(stream_data)
|
||||
ferr: Error
|
||||
switch mode {
|
||||
case .Read:
|
||||
|
||||
@@ -17,17 +17,19 @@ _ERROR_BAD_NETPATH :: 53
|
||||
MAX_RW :: 1<<30
|
||||
|
||||
|
||||
_File_Kind :: enum u8 {
|
||||
File_Impl_Kind :: enum u8 {
|
||||
File,
|
||||
Console,
|
||||
Pipe,
|
||||
}
|
||||
|
||||
_File :: struct {
|
||||
File_Impl :: struct {
|
||||
file: File,
|
||||
|
||||
fd: rawptr,
|
||||
name: string,
|
||||
wname: win32.wstring,
|
||||
kind: _File_Kind,
|
||||
kind: File_Impl_Kind,
|
||||
|
||||
allocator: runtime.Allocator,
|
||||
|
||||
@@ -75,11 +77,9 @@ _open_internal :: proc(name: string, flags: File_Flags, perm: File_Mode) -> (han
|
||||
access |= win32.FILE_APPEND_DATA
|
||||
}
|
||||
share_mode := u32(win32.FILE_SHARE_READ | win32.FILE_SHARE_WRITE)
|
||||
sa: ^win32.SECURITY_ATTRIBUTES
|
||||
if .Close_On_Exec not_in flags {
|
||||
sa = &win32.SECURITY_ATTRIBUTES{}
|
||||
sa.nLength = size_of(win32.SECURITY_ATTRIBUTES)
|
||||
sa.bInheritHandle = true
|
||||
sa := win32.SECURITY_ATTRIBUTES {
|
||||
nLength = size_of(win32.SECURITY_ATTRIBUTES),
|
||||
bInheritHandle = .Close_On_Exec not_in flags,
|
||||
}
|
||||
|
||||
create_mode: u32 = win32.OPEN_EXISTING
|
||||
@@ -101,7 +101,7 @@ _open_internal :: proc(name: string, flags: File_Flags, perm: File_Mode) -> (han
|
||||
// NOTE(bill): Open has just asked to create a file in read-only mode.
|
||||
// If the file already exists, to make it akin to a *nix open call,
|
||||
// the call preserves the existing permissions.
|
||||
h := win32.CreateFileW(path, access, share_mode, sa, win32.TRUNCATE_EXISTING, win32.FILE_ATTRIBUTE_NORMAL, nil)
|
||||
h := win32.CreateFileW(path, access, share_mode, &sa, win32.TRUNCATE_EXISTING, win32.FILE_ATTRIBUTE_NORMAL, nil)
|
||||
if h == win32.INVALID_HANDLE {
|
||||
switch e := win32.GetLastError(); e {
|
||||
case win32.ERROR_FILE_NOT_FOUND, _ERROR_BAD_NETPATH, win32.ERROR_PATH_NOT_FOUND:
|
||||
@@ -114,7 +114,7 @@ _open_internal :: proc(name: string, flags: File_Flags, perm: File_Mode) -> (han
|
||||
}
|
||||
}
|
||||
}
|
||||
h := win32.CreateFileW(path, access, share_mode, sa, create_mode, attrs, nil)
|
||||
h := win32.CreateFileW(path, access, share_mode, &sa, create_mode, attrs, nil)
|
||||
if h == win32.INVALID_HANDLE {
|
||||
return 0, _get_platform_error()
|
||||
}
|
||||
@@ -124,7 +124,7 @@ _open_internal :: proc(name: string, flags: File_Flags, perm: File_Mode) -> (han
|
||||
|
||||
_open :: proc(name: string, flags: File_Flags, perm: File_Mode) -> (f: ^File, err: Error) {
|
||||
flags := flags if flags != nil else {.Read}
|
||||
handle := _open_internal(name, flags + {.Close_On_Exec}, perm) or_return
|
||||
handle := _open_internal(name, flags, perm) or_return
|
||||
return _new_file(handle, name), nil
|
||||
}
|
||||
|
||||
@@ -132,75 +132,81 @@ _new_file :: proc(handle: uintptr, name: string) -> ^File {
|
||||
if handle == INVALID_HANDLE {
|
||||
return nil
|
||||
}
|
||||
f := new(File, file_allocator())
|
||||
impl := new(File_Impl, file_allocator())
|
||||
impl.file.impl = impl
|
||||
|
||||
f.impl.allocator = file_allocator()
|
||||
f.impl.fd = rawptr(handle)
|
||||
f.impl.name, _ = clone_string(name, f.impl.allocator)
|
||||
f.impl.wname = win32.utf8_to_wstring(name, f.impl.allocator)
|
||||
impl.allocator = file_allocator()
|
||||
impl.fd = rawptr(handle)
|
||||
impl.name, _ = clone_string(name, impl.allocator)
|
||||
impl.wname = win32.utf8_to_wstring(name, impl.allocator)
|
||||
|
||||
handle := _handle(f)
|
||||
kind := _File_Kind.File
|
||||
handle := _handle(&impl.file)
|
||||
kind := File_Impl_Kind.File
|
||||
if m: u32; win32.GetConsoleMode(handle, &m) {
|
||||
kind = .Console
|
||||
}
|
||||
if win32.GetFileType(handle) == win32.FILE_TYPE_PIPE {
|
||||
kind = .Pipe
|
||||
}
|
||||
f.impl.kind = kind
|
||||
impl.kind = kind
|
||||
|
||||
f.stream = {
|
||||
data = f,
|
||||
impl.file.stream = {
|
||||
data = impl,
|
||||
procedure = _file_stream_proc,
|
||||
}
|
||||
impl.file.fstat = _fstat
|
||||
|
||||
return f
|
||||
return &impl.file
|
||||
}
|
||||
|
||||
_fd :: proc(f: ^File) -> uintptr {
|
||||
if f == nil {
|
||||
if f == nil || f.impl == nil {
|
||||
return INVALID_HANDLE
|
||||
}
|
||||
return uintptr(f.impl.fd)
|
||||
return uintptr((^File_Impl)(f.impl).fd)
|
||||
}
|
||||
|
||||
_destroy :: proc(f: ^File) -> Error {
|
||||
_destroy :: proc(f: ^File_Impl) -> Error {
|
||||
if f == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
a := f.impl.allocator
|
||||
free(f.impl.wname, a)
|
||||
delete(f.impl.name, a)
|
||||
free(f, a)
|
||||
a := f.allocator
|
||||
err0 := free(f.wname, a)
|
||||
err1 := delete(f.name, a)
|
||||
err2 := free(f, a)
|
||||
err0 or_return
|
||||
err1 or_return
|
||||
err2 or_return
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
_close :: proc(f: ^File) -> Error {
|
||||
if f == nil {
|
||||
_close :: proc(f: ^File_Impl) -> Error {
|
||||
if f == nil {
|
||||
return nil
|
||||
}
|
||||
if !win32.CloseHandle(win32.HANDLE(f.impl.fd)) {
|
||||
if !win32.CloseHandle(win32.HANDLE(f.fd)) {
|
||||
return .Closed
|
||||
}
|
||||
return _destroy(f)
|
||||
}
|
||||
|
||||
_name :: proc(f: ^File) -> string {
|
||||
return f.impl.name if f != nil else ""
|
||||
return (^File_Impl)(f.impl).name if f != nil && f.impl != nil else ""
|
||||
}
|
||||
|
||||
_seek :: proc(f: ^File, offset: i64, whence: io.Seek_From) -> (ret: i64, err: Error) {
|
||||
handle := _handle(f)
|
||||
_seek :: proc(f: ^File_Impl, offset: i64, whence: io.Seek_From) -> (ret: i64, err: Error) {
|
||||
handle := _handle(&f.file)
|
||||
if handle == win32.INVALID_HANDLE {
|
||||
return 0, .Invalid_File
|
||||
}
|
||||
if f.impl.kind == .Pipe {
|
||||
|
||||
if f.kind == .Pipe {
|
||||
return 0, .Invalid_File
|
||||
}
|
||||
|
||||
sync.guard(&f.impl.rw_mutex)
|
||||
sync.guard(&f.rw_mutex)
|
||||
|
||||
w: u32
|
||||
switch whence {
|
||||
@@ -218,7 +224,7 @@ _seek :: proc(f: ^File, offset: i64, whence: io.Seek_From) -> (ret: i64, err: Er
|
||||
return i64(hi)<<32 + i64(dw_ptr), nil
|
||||
}
|
||||
|
||||
_read :: proc(f: ^File, p: []byte) -> (n: i64, err: Error) {
|
||||
_read :: proc(f: ^File_Impl, p: []byte) -> (n: i64, err: Error) {
|
||||
read_console :: proc(handle: win32.HANDLE, b: []byte) -> (n: int, err: Error) {
|
||||
if len(b) == 0 {
|
||||
return 0, nil
|
||||
@@ -269,18 +275,18 @@ _read :: proc(f: ^File, p: []byte) -> (n: i64, err: Error) {
|
||||
return
|
||||
}
|
||||
|
||||
handle := _handle(f)
|
||||
handle := _handle(&f.file)
|
||||
|
||||
single_read_length: win32.DWORD
|
||||
total_read: int
|
||||
length := len(p)
|
||||
|
||||
sync.shared_guard(&f.impl.rw_mutex) // multiple readers
|
||||
sync.shared_guard(&f.rw_mutex) // multiple readers
|
||||
|
||||
if sync.guard(&f.impl.p_mutex) {
|
||||
if sync.guard(&f.p_mutex) {
|
||||
to_read := min(win32.DWORD(length), MAX_RW)
|
||||
ok: win32.BOOL
|
||||
if f.impl.kind == .Console {
|
||||
if f.kind == .Console {
|
||||
n, cerr := read_console(handle, p[total_read:][:to_read])
|
||||
total_read += n
|
||||
if cerr != nil {
|
||||
@@ -300,15 +306,15 @@ _read :: proc(f: ^File, p: []byte) -> (n: i64, err: Error) {
|
||||
return i64(total_read), err
|
||||
}
|
||||
|
||||
_read_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: i64, err: Error) {
|
||||
pread :: proc(f: ^File, data: []byte, offset: i64) -> (n: i64, err: Error) {
|
||||
_read_at :: proc(f: ^File_Impl, p: []byte, offset: i64) -> (n: i64, err: Error) {
|
||||
pread :: proc(f: ^File_Impl, data: []byte, offset: i64) -> (n: i64, err: Error) {
|
||||
buf := data
|
||||
if len(buf) > MAX_RW {
|
||||
buf = buf[:MAX_RW]
|
||||
|
||||
}
|
||||
curr_offset := seek(f, offset, .Current) or_return
|
||||
defer seek(f, curr_offset, .Start)
|
||||
curr_offset := _seek(f, offset, .Current) or_return
|
||||
defer _seek(f, curr_offset, .Start)
|
||||
|
||||
o := win32.OVERLAPPED{
|
||||
OffsetHigh = u32(offset>>32),
|
||||
@@ -317,7 +323,7 @@ _read_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: i64, err: Error) {
|
||||
|
||||
// TODO(bill): Determine the correct behaviour for consoles
|
||||
|
||||
h := _handle(f)
|
||||
h := _handle(&f.file)
|
||||
done: win32.DWORD
|
||||
if !win32.ReadFile(h, raw_data(buf), u32(len(buf)), &done, &o) {
|
||||
err = _get_platform_error()
|
||||
@@ -327,7 +333,7 @@ _read_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: i64, err: Error) {
|
||||
return
|
||||
}
|
||||
|
||||
sync.guard(&f.impl.p_mutex)
|
||||
sync.guard(&f.p_mutex)
|
||||
|
||||
p, offset := p, offset
|
||||
for len(p) > 0 {
|
||||
@@ -339,7 +345,7 @@ _read_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: i64, err: Error) {
|
||||
return
|
||||
}
|
||||
|
||||
_write :: proc(f: ^File, p: []byte) -> (n: i64, err: Error) {
|
||||
_write :: proc(f: ^File_Impl, p: []byte) -> (n: i64, err: Error) {
|
||||
if len(p) == 0 {
|
||||
return
|
||||
}
|
||||
@@ -348,9 +354,9 @@ _write :: proc(f: ^File, p: []byte) -> (n: i64, err: Error) {
|
||||
total_write: i64
|
||||
length := i64(len(p))
|
||||
|
||||
handle := _handle(f)
|
||||
handle := _handle(&f.file)
|
||||
|
||||
sync.guard(&f.impl.rw_mutex)
|
||||
sync.guard(&f.rw_mutex)
|
||||
for total_write < length {
|
||||
remaining := length - total_write
|
||||
to_write := win32.DWORD(min(i32(remaining), MAX_RW))
|
||||
@@ -366,22 +372,22 @@ _write :: proc(f: ^File, p: []byte) -> (n: i64, err: Error) {
|
||||
return i64(total_write), nil
|
||||
}
|
||||
|
||||
_write_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: i64, err: Error) {
|
||||
pwrite :: proc(f: ^File, data: []byte, offset: i64) -> (n: i64, err: Error) {
|
||||
_write_at :: proc(f: ^File_Impl, p: []byte, offset: i64) -> (n: i64, err: Error) {
|
||||
pwrite :: proc(f: ^File_Impl, data: []byte, offset: i64) -> (n: i64, err: Error) {
|
||||
buf := data
|
||||
if len(buf) > MAX_RW {
|
||||
buf = buf[:MAX_RW]
|
||||
|
||||
}
|
||||
curr_offset := seek(f, offset, .Current) or_return
|
||||
defer seek(f, curr_offset, .Start)
|
||||
curr_offset := _seek(f, offset, .Current) or_return
|
||||
defer _seek(f, curr_offset, .Start)
|
||||
|
||||
o := win32.OVERLAPPED{
|
||||
OffsetHigh = u32(offset>>32),
|
||||
Offset = u32(offset),
|
||||
}
|
||||
|
||||
h := _handle(f)
|
||||
h := _handle(&f.file)
|
||||
done: win32.DWORD
|
||||
if !win32.WriteFile(h, raw_data(buf), u32(len(buf)), &done, &o) {
|
||||
err = _get_platform_error()
|
||||
@@ -391,7 +397,7 @@ _write_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: i64, err: Error) {
|
||||
return
|
||||
}
|
||||
|
||||
sync.guard(&f.impl.p_mutex)
|
||||
sync.guard(&f.p_mutex)
|
||||
p, offset := p, offset
|
||||
for len(p) > 0 {
|
||||
m := pwrite(f, p, offset) or_return
|
||||
@@ -402,12 +408,12 @@ _write_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: i64, err: Error) {
|
||||
return
|
||||
}
|
||||
|
||||
_file_size :: proc(f: ^File) -> (n: i64, err: Error) {
|
||||
_file_size :: proc(f: ^File_Impl) -> (n: i64, err: Error) {
|
||||
length: win32.LARGE_INTEGER
|
||||
if f.impl.kind == .Pipe {
|
||||
if f.kind == .Pipe {
|
||||
return 0, .No_Size
|
||||
}
|
||||
handle := _handle(f)
|
||||
handle := _handle(&f.file)
|
||||
if !win32.GetFileSizeEx(handle, &length) {
|
||||
err = _get_platform_error()
|
||||
}
|
||||
@@ -417,11 +423,14 @@ _file_size :: proc(f: ^File) -> (n: i64, err: Error) {
|
||||
|
||||
|
||||
_sync :: proc(f: ^File) -> Error {
|
||||
return _flush(f)
|
||||
if f != nil && f.impl != nil {
|
||||
return _flush((^File_Impl)(f.impl))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
_flush :: proc(f: ^File) -> Error {
|
||||
handle := _handle(f)
|
||||
_flush :: proc(f: ^File_Impl) -> Error {
|
||||
handle := _handle(&f.file)
|
||||
if !win32.FlushFileBuffers(handle) {
|
||||
return _get_platform_error()
|
||||
}
|
||||
@@ -429,7 +438,7 @@ _flush :: proc(f: ^File) -> Error {
|
||||
}
|
||||
|
||||
_truncate :: proc(f: ^File, size: i64) -> Error {
|
||||
if f == nil {
|
||||
if f == nil || f.impl == nil {
|
||||
return nil
|
||||
}
|
||||
curr_off := seek(f, 0, .Current) or_return
|
||||
@@ -616,17 +625,18 @@ _read_link :: proc(name: string, allocator: runtime.Allocator) -> (s: string, er
|
||||
|
||||
|
||||
_fchdir :: proc(f: ^File) -> Error {
|
||||
if f == nil {
|
||||
if f == nil || f.impl == nil {
|
||||
return nil
|
||||
}
|
||||
if !win32.SetCurrentDirectoryW(f.impl.wname) {
|
||||
impl := (^File_Impl)(f.impl)
|
||||
if !win32.SetCurrentDirectoryW(impl.wname) {
|
||||
return _get_platform_error()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
_fchmod :: proc(f: ^File, mode: File_Mode) -> Error {
|
||||
if f == nil {
|
||||
if f == nil || f.impl == nil {
|
||||
return nil
|
||||
}
|
||||
d: win32.BY_HANDLE_FILE_INFORMATION
|
||||
@@ -681,7 +691,7 @@ _chtimes :: proc(name: string, atime, mtime: time.Time) -> Error {
|
||||
return _fchtimes(f, atime, mtime)
|
||||
}
|
||||
_fchtimes :: proc(f: ^File, atime, mtime: time.Time) -> Error {
|
||||
if f == nil {
|
||||
if f == nil || f.impl == nil {
|
||||
return nil
|
||||
}
|
||||
d: win32.BY_HANDLE_FILE_INFORMATION
|
||||
@@ -737,7 +747,7 @@ _is_dir :: proc(path: string) -> bool {
|
||||
|
||||
@(private="package")
|
||||
_file_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) {
|
||||
f := (^File)(stream_data)
|
||||
f := (^File_Impl)(stream_data)
|
||||
ferr: Error
|
||||
switch mode {
|
||||
case .Read:
|
||||
|
||||
@@ -29,10 +29,12 @@ file_info_delete :: proc(fi: File_Info, allocator: runtime.Allocator) {
|
||||
|
||||
@(require_results)
|
||||
fstat :: proc(f: ^File, allocator: runtime.Allocator) -> (File_Info, Error) {
|
||||
if f != nil && f.user_fstat != nil {
|
||||
return f->user_fstat(allocator)
|
||||
if f == nil {
|
||||
return {}, nil
|
||||
} else if f.fstat != nil {
|
||||
return f->fstat(allocator)
|
||||
}
|
||||
return _fstat(f, allocator)
|
||||
return {}, .Invalid_Callback
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
|
||||
@@ -7,7 +7,8 @@ import "core:sys/linux"
|
||||
import "core:path/filepath"
|
||||
|
||||
_fstat :: proc(f: ^File, allocator: runtime.Allocator) -> (File_Info, Error) {
|
||||
return _fstat_internal(f.impl.fd, allocator)
|
||||
impl := (^File_Impl)(f.impl)
|
||||
return _fstat_internal(impl.fd, allocator)
|
||||
}
|
||||
|
||||
_fstat_internal :: proc(fd: linux.Fd, allocator: runtime.Allocator) -> (File_Info, Error) {
|
||||
|
||||
@@ -7,7 +7,7 @@ import "core:strings"
|
||||
import win32 "core:sys/windows"
|
||||
|
||||
_fstat :: proc(f: ^File, allocator: runtime.Allocator) -> (File_Info, Error) {
|
||||
if f == nil || f.impl.fd == nil {
|
||||
if f == nil || (^File_Impl)(f.impl).fd == nil {
|
||||
return {}, nil
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ _cleanpath_strip_prefix :: proc(buf: []u16) -> []u16 {
|
||||
|
||||
|
||||
_cleanpath_from_handle :: proc(f: ^File, allocator: runtime.Allocator) -> (string, Error) {
|
||||
if f == nil || f.impl.fd == nil {
|
||||
if f == nil {
|
||||
return "", nil
|
||||
}
|
||||
h := _handle(f)
|
||||
@@ -138,7 +138,7 @@ _cleanpath_from_handle :: proc(f: ^File, allocator: runtime.Allocator) -> (strin
|
||||
}
|
||||
|
||||
_cleanpath_from_handle_u16 :: proc(f: ^File) -> ([]u16, Error) {
|
||||
if f == nil || f.impl.fd == nil {
|
||||
if f == nil {
|
||||
return nil, nil
|
||||
}
|
||||
h := _handle(f)
|
||||
|
||||
@@ -18,6 +18,14 @@ foreign advapi32 {
|
||||
OpenAsSelf: BOOL,
|
||||
TokenHandle: ^HANDLE) -> BOOL ---
|
||||
|
||||
GetTokenInformation :: proc (
|
||||
TokenHandle: HANDLE,
|
||||
TokenInformationClass: TOKEN_INFORMATION_CLASS,
|
||||
TokenInformation: LPVOID,
|
||||
TokenInformationLength: DWORD,
|
||||
ReturnLength: PDWORD,
|
||||
) -> BOOL ---
|
||||
|
||||
CryptAcquireContextW :: proc(hProv: ^HCRYPTPROV, szContainer, szProvider: wstring, dwProvType, dwFlags: DWORD) -> DWORD ---
|
||||
CryptGenRandom :: proc(hProv: HCRYPTPROV, dwLen: DWORD, buf: LPVOID) -> DWORD ---
|
||||
CryptReleaseContext :: proc(hProv: HCRYPTPROV, dwFlags: DWORD) -> DWORD ---
|
||||
@@ -44,7 +52,17 @@ foreign advapi32 {
|
||||
cbSid: ^DWORD,
|
||||
ReferencedDomainName: wstring,
|
||||
cchReferencedDomainName: ^DWORD,
|
||||
peUse: ^SID_TYPE,
|
||||
peUse: PSID_NAME_USE,
|
||||
) -> BOOL ---
|
||||
|
||||
LookupAccountSidW :: proc (
|
||||
lpSystemName: LPCWSTR,
|
||||
Sid: PSID,
|
||||
Name: LPWSTR,
|
||||
cchName: LPDWORD,
|
||||
ReferencedDomainName: LPWSTR,
|
||||
cchReferencedDomainName: LPDWORD,
|
||||
peUse: PSID_NAME_USE,
|
||||
) -> BOOL ---
|
||||
|
||||
CreateProcessWithLogonW :: proc(
|
||||
@@ -164,3 +182,156 @@ foreign advapi32 {
|
||||
AccessStatus: LPBOOL,
|
||||
) -> BOOL ---
|
||||
}
|
||||
|
||||
PTOKEN_INFORMATION_CLASS :: ^TOKEN_INFORMATION_CLASS
|
||||
TOKEN_INFORMATION_CLASS :: enum i32 {
|
||||
TokenUser = 1,
|
||||
TokenGroups,
|
||||
TokenPrivileges,
|
||||
TokenOwner,
|
||||
TokenPrimaryGroup,
|
||||
TokenDefaultDacl,
|
||||
TokenSource,
|
||||
TokenType,
|
||||
TokenImpersonationLevel,
|
||||
TokenStatistics,
|
||||
TokenRestrictedSids,
|
||||
TokenSessionId,
|
||||
TokenGroupsAndPrivileges,
|
||||
TokenSessionReference,
|
||||
TokenSandBoxInert,
|
||||
TokenAuditPolicy,
|
||||
TokenOrigin,
|
||||
TokenElevationType,
|
||||
TokenLinkedToken,
|
||||
TokenElevation,
|
||||
TokenHasRestrictions,
|
||||
TokenAccessInformation,
|
||||
TokenVirtualizationAllowed,
|
||||
TokenVirtualizationEnabled,
|
||||
TokenIntegrityLevel,
|
||||
TokenUIAccess,
|
||||
TokenMandatoryPolicy,
|
||||
TokenLogonSid,
|
||||
TokenIsAppContainer,
|
||||
TokenCapabilities,
|
||||
TokenAppContainerSid,
|
||||
TokenAppContainerNumber,
|
||||
TokenUserClaimAttributes,
|
||||
TokenDeviceClaimAttributes,
|
||||
TokenRestrictedUserClaimAttributes,
|
||||
TokenRestrictedDeviceClaimAttributes,
|
||||
TokenDeviceGroups,
|
||||
TokenRestrictedDeviceGroups,
|
||||
TokenSecurityAttributes,
|
||||
TokenIsRestricted,
|
||||
TokenProcessTrustLevel,
|
||||
TokenPrivateNameSpace,
|
||||
TokenSingletonAttributes,
|
||||
TokenBnoIsolation,
|
||||
TokenChildProcessFlags,
|
||||
TokenIsLessPrivilegedAppContainer,
|
||||
TokenIsSandboxed,
|
||||
TokenIsAppSilo,
|
||||
TokenLoggingInformation,
|
||||
MaxTokenInfoClass,
|
||||
}
|
||||
|
||||
PSID_NAME_USE :: ^SID_NAME_USE
|
||||
SID_NAME_USE :: enum i32 {
|
||||
SidTypeUser = 1,
|
||||
SidTypeGroup,
|
||||
SidTypeDomain,
|
||||
SidTypeAlias,
|
||||
SidTypeWellKnownGroup,
|
||||
SidTypeDeletedAccount,
|
||||
SidTypeInvalid,
|
||||
SidTypeUnknown,
|
||||
SidTypeComputer,
|
||||
SidTypeLabel,
|
||||
SidTypeLogonSession,
|
||||
}
|
||||
|
||||
PTOKEN_USER :: ^TOKEN_USER
|
||||
TOKEN_USER :: struct {
|
||||
User: SID_AND_ATTRIBUTES,
|
||||
}
|
||||
|
||||
PSID_AND_ATTRIBUTES :: ^SID_AND_ATTRIBUTES
|
||||
SID_AND_ATTRIBUTES :: struct {
|
||||
Sid: rawptr,
|
||||
Attributes: ULONG,
|
||||
}
|
||||
|
||||
PTOKEN_TYPE :: ^TOKEN_TYPE
|
||||
TOKEN_TYPE :: enum {
|
||||
TokenPrimary = 1,
|
||||
TokenImpersonation = 2,
|
||||
}
|
||||
|
||||
PTOKEN_STATISTICS :: ^TOKEN_STATISTICS
|
||||
TOKEN_STATISTICS :: struct {
|
||||
TokenId: LUID,
|
||||
AuthenticationId: LUID,
|
||||
ExpirationTime: LARGE_INTEGER,
|
||||
TokenType: TOKEN_TYPE,
|
||||
ImpersonationLevel: SECURITY_IMPERSONATION_LEVEL,
|
||||
DynamicCharged: DWORD,
|
||||
DynamicAvailable: DWORD,
|
||||
GroupCount: DWORD,
|
||||
PrivilegeCount: DWORD,
|
||||
ModifiedId: LUID,
|
||||
}
|
||||
|
||||
|
||||
TOKEN_SOURCE_LENGTH :: 8
|
||||
PTOKEN_SOURCE :: ^TOKEN_SOURCE
|
||||
TOKEN_SOURCE :: struct {
|
||||
SourceName: [TOKEN_SOURCE_LENGTH]CHAR,
|
||||
SourceIdentifier: LUID,
|
||||
}
|
||||
|
||||
|
||||
PTOKEN_PRIVILEGES :: ^TOKEN_PRIVILEGES
|
||||
TOKEN_PRIVILEGES :: struct {
|
||||
PrivilegeCount: DWORD,
|
||||
Privileges: [0]LUID_AND_ATTRIBUTES,
|
||||
}
|
||||
|
||||
PTOKEN_PRIMARY_GROUP :: ^TOKEN_PRIMARY_GROUP
|
||||
TOKEN_PRIMARY_GROUP :: struct {
|
||||
PrimaryGroup: PSID,
|
||||
}
|
||||
|
||||
PTOKEN_OWNER :: ^TOKEN_OWNER
|
||||
TOKEN_OWNER :: struct {
|
||||
Owner: PSID,
|
||||
}
|
||||
|
||||
PTOKEN_GROUPS_AND_PRIVILEGES :: ^TOKEN_GROUPS_AND_PRIVILEGES
|
||||
TOKEN_GROUPS_AND_PRIVILEGES :: struct {
|
||||
SidCount: DWORD,
|
||||
SidLength: DWORD,
|
||||
Sids: PSID_AND_ATTRIBUTES,
|
||||
RestrictedSidCount: DWORD,
|
||||
RestrictedSidLength: DWORD,
|
||||
RestrictedSids: PSID_AND_ATTRIBUTES,
|
||||
PrivilegeCount: DWORD,
|
||||
PrivilegeLength: DWORD,
|
||||
Privileges: PLUID_AND_ATTRIBUTES,
|
||||
AuthenticationId: LUID,
|
||||
}
|
||||
|
||||
PTOKEN_DEFAULT_DACL :: ^TOKEN_DEFAULT_DACL
|
||||
TOKEN_DEFAULT_DACL :: struct {
|
||||
DefaultDacl: PACL,
|
||||
}
|
||||
|
||||
PACL :: ^ACL
|
||||
ACL :: struct {
|
||||
AclRevision: BYTE,
|
||||
Sbz1: BYTE,
|
||||
AclSize: WORD,
|
||||
AceCount: WORD,
|
||||
Sbz2: WORD,
|
||||
}
|
||||
|
||||
@@ -233,6 +233,12 @@ foreign kernel32 {
|
||||
QueryPerformanceCounter :: proc(lpPerformanceCount: ^LARGE_INTEGER) -> BOOL ---
|
||||
GetExitCodeProcess :: proc(hProcess: HANDLE, lpExitCode: LPDWORD) -> BOOL ---
|
||||
TerminateProcess :: proc(hProcess: HANDLE, uExitCode: UINT) -> BOOL ---
|
||||
OpenProcess :: proc(dwDesiredAccess: DWORD, bInheritHandle: BOOL, dwProcessId: DWORD) -> HANDLE ---
|
||||
OpenThread :: proc(dwDesiredAccess: DWORD, bInheritHandle: BOOL, dwThreadId: DWORD) -> HANDLE ---
|
||||
GetThreadContext :: proc(
|
||||
hThread: HANDLE,
|
||||
lpContext: LPCONTEXT,
|
||||
) -> BOOL ---
|
||||
CreateProcessW :: proc(
|
||||
lpApplicationName: LPCWSTR,
|
||||
lpCommandLine: LPWSTR,
|
||||
@@ -543,6 +549,45 @@ THREAD_PRIORITY_IDLE :: THREAD_BASE_PRIORITY_IDLE
|
||||
THREAD_MODE_BACKGROUND_BEGIN :: 0x00010000
|
||||
THREAD_MODE_BACKGROUND_END :: 0x00020000
|
||||
|
||||
PROCESS_ALL_ACCESS :: 0x000F0000 | SYNCHRONIZE | 0xFFFF
|
||||
PROCESS_CREATE_PROCESS :: 0x0080
|
||||
PROCESS_CREATE_THREAD :: 0x0002
|
||||
PROCESS_DUP_HANDLE :: 0x0040
|
||||
PROCESS_QUERY_INFORMATION :: 0x0400
|
||||
PROCESS_QUERY_LIMITED_INFORMATION :: 0x1000
|
||||
PROCESS_SET_INFORMATION :: 0x0200
|
||||
PROCESS_SET_QUOTA :: 0x0100
|
||||
PROCESS_SUSPEND_RESUME :: 0x0800
|
||||
PROCESS_TERMINATE :: 0x0001
|
||||
PROCESS_VM_OPERATION :: 0x0008
|
||||
PROCESS_VM_READ :: 0x0010
|
||||
PROCESS_VM_WRITE :: 0x0020
|
||||
|
||||
THREAD_ALL_ACCESS :: \
|
||||
THREAD_DIRECT_IMPERSONATION |
|
||||
THREAD_GET_CONTEXT |
|
||||
THREAD_IMPERSONATE |
|
||||
THREAD_QUERY_INFORMATION |
|
||||
THREAD_QUERY_LIMITED_INFORMATION |
|
||||
THREAD_SET_CONTEXT |
|
||||
THREAD_SET_INFORMATION |
|
||||
THREAD_SET_LIMITED_INFORMATION |
|
||||
THREAD_SET_THREAD_TOKEN |
|
||||
THREAD_SUSPEND_RESUME |
|
||||
THREAD_TERMINATE |
|
||||
SYNCHRONIZE
|
||||
THREAD_DIRECT_IMPERSONATION :: 0x0200
|
||||
THREAD_GET_CONTEXT :: 0x0008
|
||||
THREAD_IMPERSONATE :: 0x0100
|
||||
THREAD_QUERY_INFORMATION :: 0x0040
|
||||
THREAD_QUERY_LIMITED_INFORMATION :: 0x0800
|
||||
THREAD_SET_CONTEXT :: 0x0010
|
||||
THREAD_SET_INFORMATION :: 0x0020
|
||||
THREAD_SET_LIMITED_INFORMATION :: 0x0400
|
||||
THREAD_SET_THREAD_TOKEN :: 0x0080
|
||||
THREAD_SUSPEND_RESUME :: 0x0002
|
||||
THREAD_TERMINATE :: 0x0001
|
||||
|
||||
COPY_FILE_FAIL_IF_EXISTS :: 0x00000001
|
||||
COPY_FILE_RESTARTABLE :: 0x00000002
|
||||
COPY_FILE_OPEN_SOURCE_FOR_WRITE :: 0x00000004
|
||||
|
||||
+135
-18
@@ -64,6 +64,7 @@ LONG_PTR :: int
|
||||
UINT_PTR :: uintptr
|
||||
ULONG :: c_ulong
|
||||
ULONGLONG :: c_ulonglong
|
||||
LONGLONG :: c_longlong
|
||||
UCHAR :: BYTE
|
||||
NTSTATUS :: c.long
|
||||
COLORREF :: DWORD
|
||||
@@ -2145,6 +2146,7 @@ SECURITY_IMPERSONATION_LEVEL :: enum {
|
||||
SECURITY_INFORMATION :: DWORD
|
||||
ANYSIZE_ARRAY :: 1
|
||||
|
||||
PLUID_AND_ATTRIBUTES :: ^LUID_AND_ATTRIBUTES
|
||||
LUID_AND_ATTRIBUTES :: struct {
|
||||
Luid: LUID,
|
||||
Attributes: DWORD,
|
||||
@@ -2570,7 +2572,139 @@ EXCEPTION_RECORD :: struct {
|
||||
ExceptionInformation: [EXCEPTION_MAXIMUM_PARAMETERS]LPVOID,
|
||||
}
|
||||
|
||||
CONTEXT :: struct{} // TODO(bill)
|
||||
|
||||
CONTEXT :: struct {
|
||||
P1Home: DWORD64,
|
||||
P2Home: DWORD64,
|
||||
P3Home: DWORD64,
|
||||
P4Home: DWORD64,
|
||||
P5Home: DWORD64,
|
||||
P6Home: DWORD64,
|
||||
ContextFlags: DWORD,
|
||||
MxCsr: DWORD,
|
||||
SegCs: WORD,
|
||||
SegDs: WORD,
|
||||
SegEs: WORD,
|
||||
SegFs: WORD,
|
||||
SegGs: WORD,
|
||||
SegSs: WORD,
|
||||
EFlags: DWORD,
|
||||
Dr0: DWORD64,
|
||||
Dr1: DWORD64,
|
||||
Dr2: DWORD64,
|
||||
Dr3: DWORD64,
|
||||
Dr6: DWORD64,
|
||||
Dr7: DWORD64,
|
||||
Rax: DWORD64,
|
||||
Rcx: DWORD64,
|
||||
Rdx: DWORD64,
|
||||
Rbx: DWORD64,
|
||||
Rsp: DWORD64,
|
||||
Rbp: DWORD64,
|
||||
Rsi: DWORD64,
|
||||
Rdi: DWORD64,
|
||||
R8: DWORD64,
|
||||
R9: DWORD64,
|
||||
R10: DWORD64,
|
||||
R11: DWORD64,
|
||||
R12: DWORD64,
|
||||
R13: DWORD64,
|
||||
R14: DWORD64,
|
||||
R15: DWORD64,
|
||||
Rip: DWORD64,
|
||||
_: struct #raw_union {
|
||||
FltSave: XMM_SAVE_AREA32,
|
||||
Q: [16]NEON128,
|
||||
D: [32]ULONGLONG,
|
||||
_: struct {
|
||||
Header: [2]M128A,
|
||||
Legacy: [8]M128A,
|
||||
Xmm0: M128A,
|
||||
Xmm1: M128A,
|
||||
Xmm2: M128A,
|
||||
Xmm3: M128A,
|
||||
Xmm4: M128A,
|
||||
Xmm5: M128A,
|
||||
Xmm6: M128A,
|
||||
Xmm7: M128A,
|
||||
Xmm8: M128A,
|
||||
Xmm9: M128A,
|
||||
Xmm10: M128A,
|
||||
Xmm11: M128A,
|
||||
Xmm12: M128A,
|
||||
Xmm13: M128A,
|
||||
Xmm14: M128A,
|
||||
Xmm15: M128A,
|
||||
},
|
||||
S: [32]DWORD,
|
||||
},
|
||||
VectorRegister: [26]M128A,
|
||||
VectorControl: DWORD64,
|
||||
DebugControl: DWORD64,
|
||||
LastBranchToRip: DWORD64,
|
||||
LastBranchFromRip: DWORD64,
|
||||
LastExceptionToRip: DWORD64,
|
||||
LastExceptionFromRip: DWORD64,
|
||||
}
|
||||
|
||||
PCONTEXT :: ^CONTEXT
|
||||
LPCONTEXT :: ^CONTEXT
|
||||
|
||||
when size_of(uintptr) == 32 {
|
||||
XSAVE_FORMAT :: struct #align(16) {
|
||||
ControlWord: WORD,
|
||||
StatusWord: WORD,
|
||||
TagWord: BYTE,
|
||||
Reserved1: BYTE,
|
||||
ErrorOpcode: WORD,
|
||||
ErrorOffset: DWORD,
|
||||
ErrorSelector: WORD,
|
||||
Reserved2: WORD,
|
||||
DataOffset: DWORD,
|
||||
DataSelector: WORD,
|
||||
Reserved3: WORD,
|
||||
MxCsr: DWORD,
|
||||
MxCsr_Mask: DWORD,
|
||||
FloatRegisters: [8]M128A,
|
||||
// 32-bit specific
|
||||
XmmRegisters: [8]M128A,
|
||||
Reserved4: [192]BYTE,
|
||||
StackControl: [7]DWORD,
|
||||
Cr0NpxState: DWORD,
|
||||
}
|
||||
} else {
|
||||
XSAVE_FORMAT :: struct #align(16) {
|
||||
ControlWord: WORD,
|
||||
StatusWord: WORD,
|
||||
TagWord: BYTE,
|
||||
Reserved1: BYTE,
|
||||
ErrorOpcode: WORD,
|
||||
ErrorOffset: DWORD,
|
||||
ErrorSelector: WORD,
|
||||
Reserved2: WORD,
|
||||
DataOffset: DWORD,
|
||||
DataSelector: WORD,
|
||||
Reserved3: WORD,
|
||||
MxCsr: DWORD,
|
||||
MxCsr_Mask: DWORD,
|
||||
FloatRegisters: [8]M128A,
|
||||
// 64-bit specific
|
||||
XmmRegisters: [16]M128A,
|
||||
Reserved4: [96]BYTE,
|
||||
}
|
||||
}
|
||||
|
||||
XMM_SAVE_AREA32 :: XSAVE_FORMAT
|
||||
|
||||
M128A :: struct {
|
||||
Low: ULONGLONG,
|
||||
High: LONGLONG,
|
||||
}
|
||||
|
||||
NEON128 :: struct {
|
||||
Low: ULONGLONG,
|
||||
High: LONGLONG,
|
||||
}
|
||||
|
||||
EXCEPTION_POINTERS :: struct {
|
||||
ExceptionRecord: ^EXCEPTION_RECORD,
|
||||
@@ -2733,23 +2867,6 @@ PROFILEINFOW :: struct {
|
||||
hProfile: HANDLE,
|
||||
}
|
||||
|
||||
// Used in LookupAccountNameW
|
||||
SID_NAME_USE :: distinct DWORD
|
||||
|
||||
SID_TYPE :: enum SID_NAME_USE {
|
||||
User = 1,
|
||||
Group,
|
||||
Domain,
|
||||
Alias,
|
||||
WellKnownGroup,
|
||||
DeletedAccount,
|
||||
Invalid,
|
||||
Unknown,
|
||||
Computer,
|
||||
Label,
|
||||
LogonSession,
|
||||
}
|
||||
|
||||
SECURITY_MAX_SID_SIZE :: 68
|
||||
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-sid
|
||||
|
||||
@@ -202,7 +202,7 @@ get_computer_name_and_account_sid :: proc(username: string) -> (computer_name: s
|
||||
username_w := utf8_to_utf16(username, context.temp_allocator)
|
||||
cbsid: DWORD
|
||||
computer_name_size: DWORD
|
||||
pe_use := SID_TYPE.User
|
||||
pe_use := SID_NAME_USE.SidTypeUser
|
||||
|
||||
res := LookupAccountNameW(
|
||||
nil, // Look on this computer first
|
||||
@@ -244,7 +244,7 @@ get_sid :: proc(username: string, sid: ^SID) -> (ok: bool) {
|
||||
username_w := utf8_to_utf16(username, context.temp_allocator)
|
||||
cbsid: DWORD
|
||||
computer_name_size: DWORD
|
||||
pe_use := SID_TYPE.User
|
||||
pe_use := SID_NAME_USE.SidTypeUser
|
||||
|
||||
res := LookupAccountNameW(
|
||||
nil, // Look on this computer first
|
||||
|
||||
Reference in New Issue
Block a user