| author | |
| committer | |
| log | c4262da8de025ca0236df9ebb823b727ca3d43fd |
| tree | 855c75970e6f82889f71a43e27d79216058b439b |
| parent | a4310cf8b4f104802360cb854e2dcc48802301a6 |
7 files changed, 191 insertions(+), 36 deletions(-)
std/debug.zig+8-4| ... | @@ -974,9 +974,13 @@ fn globalAlloc(self: &mem.Allocator, n: usize, alignment: usize) -> %[]u8 { | ... | @@ -974,9 +974,13 @@ fn globalAlloc(self: &mem.Allocator, n: usize, alignment: usize) -> %[]u8 { |
| 974 | } | 974 | } |
| 975 | 975 | ||
| 976 | fn globalRealloc(self: &mem.Allocator, old_mem: []u8, new_size: usize, alignment: usize) -> %[]u8 { | 976 | fn globalRealloc(self: &mem.Allocator, old_mem: []u8, new_size: usize, alignment: usize) -> %[]u8 { |
| 977 | const result = %return globalAlloc(self, new_size, alignment); | 977 | if (new_size <= old_mem.len) { |
| 978 | @memcpy(result.ptr, old_mem.ptr, old_mem.len); | 978 | return old_mem[0..new_size]; |
| 979 | return result; | 979 | } else { |
| 980 | const result = %return globalAlloc(self, new_size, alignment); | ||
| 981 | @memcpy(result.ptr, old_mem.ptr, old_mem.len); | ||
| 982 | return result; | ||
| 983 | } | ||
| 980 | } | 984 | } |
| 981 | 985 | ||
| 982 | fn globalFree(self: &mem.Allocator, ptr: &u8) { } | 986 | fn globalFree(self: &mem.Allocator, memory: []u8) { } |
std/io.zig+2-2| ... | @@ -65,7 +65,7 @@ error SystemFdQuotaExceeded; | ... | @@ -65,7 +65,7 @@ error SystemFdQuotaExceeded; |
| 65 | error NameTooLong; | 65 | error NameTooLong; |
| 66 | error NoDevice; | 66 | error NoDevice; |
| 67 | error PathNotFound; | 67 | error PathNotFound; |
| 68 | error NoMem; | 68 | error OutOfMemory; |
| 69 | error Unseekable; | 69 | error Unseekable; |
| 70 | error EndOfFile; | 70 | error EndOfFile; |
| 71 | error NoStdHandles; | 71 | error NoStdHandles; |
| ... | @@ -394,7 +394,7 @@ pub const InStream = struct { | ... | @@ -394,7 +394,7 @@ pub const InStream = struct { |
| 394 | if (err > 0) { | 394 | if (err > 0) { |
| 395 | return switch (err) { | 395 | return switch (err) { |
| 396 | system.EBADF => error.BadFd, | 396 | system.EBADF => error.BadFd, |
| 397 | system.ENOMEM => error.NoMem, | 397 | system.ENOMEM => error.OutOfMemory, |
| 398 | else => error.Unexpected, | 398 | else => error.Unexpected, |
| 399 | } | 399 | } |
| 400 | } | 400 | } |
std/mem.zig+48-22| ... | @@ -8,17 +8,22 @@ const Os = builtin.Os; | ... | @@ -8,17 +8,22 @@ const Os = builtin.Os; |
| 8 | 8 | ||
| 9 | pub const Cmp = math.Cmp; | 9 | pub const Cmp = math.Cmp; |
| 10 | 10 | ||
| 11 | error NoMem; | 11 | error OutOfMemory; |
| 12 | 12 | ||
| 13 | pub const Allocator = struct { | 13 | pub const Allocator = struct { |
| 14 | /// Allocate byte_count bytes and return them in a slice, with the | 14 | /// Allocate byte_count bytes and return them in a slice, with the |
| 15 | /// slicer's pointer aligned at least to alignment bytes. | 15 | /// slicer's pointer aligned at least to alignment bytes. |
| 16 | allocFn: fn (self: &Allocator, byte_count: usize, alignment: usize) -> %[]u8, | 16 | allocFn: fn (self: &Allocator, byte_count: usize, alignment: usize) -> %[]u8, |
| 17 | 17 | ||
| 18 | /// Guaranteed: old_mem.len > 0 and alignment >= alignment of old_mem.ptr | 18 | /// Guaranteed: `old_mem.len` is the same as what was returned from allocFn or reallocFn. |
| 19 | /// Guaranteed: alignment >= alignment of old_mem.ptr | ||
| 20 | /// | ||
| 21 | /// If `new_byte_count` is less than or equal to `old_mem.len` this function must | ||
| 22 | /// return successfully. | ||
| 19 | reallocFn: fn (self: &Allocator, old_mem: []u8, new_byte_count: usize, alignment: usize) -> %[]u8, | 23 | reallocFn: fn (self: &Allocator, old_mem: []u8, new_byte_count: usize, alignment: usize) -> %[]u8, |
| 20 | 24 | ||
| 21 | freeFn: fn (self: &Allocator, ptr: &u8), | 25 | /// Guaranteed: `old_mem.len` is the same as what was returned from `allocFn` or `reallocFn` |
| 26 | freeFn: fn (self: &Allocator, old_mem: []u8), | ||
| 22 | 27 | ||
| 23 | fn create(self: &Allocator, comptime T: type) -> %&T { | 28 | fn create(self: &Allocator, comptime T: type) -> %&T { |
| 24 | const slice = %return self.alloc(T, 1); | 29 | const slice = %return self.alloc(T, 1); |
| ... | @@ -41,24 +46,41 @@ pub const Allocator = struct { | ... | @@ -41,24 +46,41 @@ pub const Allocator = struct { |
| 41 | } | 46 | } |
| 42 | 47 | ||
| 43 | // Assert that old_mem.ptr is properly aligned. | 48 | // Assert that old_mem.ptr is properly aligned. |
| 44 | _ = @alignCast(@alignOf(T), old_mem.ptr); | 49 | const aligned_old_mem = @alignCast(@alignOf(T), old_mem); |
| 45 | 50 | ||
| 46 | const byte_count = %return math.mul(usize, @sizeOf(T), n); | 51 | const byte_count = %return math.mul(usize, @sizeOf(T), n); |
| 47 | const byte_slice = %return self.reallocFn(self, ([]u8)(old_mem), byte_count, @alignOf(T)); | 52 | const byte_slice = %return self.reallocFn(self, ([]u8)(aligned_old_mem), byte_count, @alignOf(T)); |
| 48 | ([]T)(@alignCast(@alignOf(T), byte_slice)) | 53 | return ([]T)(@alignCast(@alignOf(T), byte_slice)); |
| 54 | } | ||
| 55 | |||
| 56 | /// Reallocate, but `n` must be less than or equal to `old_mem.len`. | ||
| 57 | /// Unlike `realloc`, this function cannot fail. | ||
| 58 | /// Shrinking to 0 is the same as calling `free`. | ||
| 59 | fn shrink(self: &Allocator, comptime T: type, old_mem: []T, n: usize) -> []T { | ||
| 60 | if (n == 0) { | ||
| 61 | self.free(old_mem); | ||
| 62 | return old_mem[0..0]; | ||
| 63 | } | ||
| 64 | |||
| 65 | assert(n <= old_mem.len); | ||
| 66 | |||
| 67 | // Assert that old_mem.ptr is properly aligned. | ||
| 68 | const aligned_old_mem = @alignCast(@alignOf(T), old_mem); | ||
| 69 | |||
| 70 | // Here we skip the overflow checking on the multiplication because | ||
| 71 | // n <= old_mem.len and the multiplication didn't overflow for that operation. | ||
| 72 | const byte_count = @sizeOf(T) * n; | ||
| 73 | |||
| 74 | const byte_slice = %%self.reallocFn(self, ([]u8)(aligned_old_mem), byte_count, @alignOf(T)); | ||
| 75 | return ([]T)(@alignCast(@alignOf(T), byte_slice)); | ||
| 49 | } | 76 | } |
| 50 | 77 | ||
| 51 | fn free(self: &Allocator, memory: var) { | 78 | fn free(self: &Allocator, memory: var) { |
| 52 | const ptr = if (@typeId(@typeOf(memory)) == builtin.TypeId.Pointer) { | 79 | const bytes = ([]const u8)(memory); |
| 53 | memory | 80 | if (bytes.len == 0) |
| 54 | } else { | 81 | return; |
| 55 | const const_slice = ([]const u8)(memory); | 82 | const non_const_ptr = @intToPtr(&u8, @ptrToInt(bytes.ptr)); |
| 56 | if (memory.len == 0) | 83 | self.freeFn(self, non_const_ptr[0..bytes.len]); |
| 57 | return; | ||
| 58 | const_slice.ptr | ||
| 59 | }; | ||
| 60 | const non_const_ptr = @intToPtr(&u8, @ptrToInt(ptr)); | ||
| 61 | self.freeFn(self, non_const_ptr); | ||
| 62 | } | 84 | } |
| 63 | }; | 85 | }; |
| 64 | 86 | ||
| ... | @@ -74,7 +96,7 @@ pub const IncrementingAllocator = struct { | ... | @@ -74,7 +96,7 @@ pub const IncrementingAllocator = struct { |
| 74 | const addr = p.mmap(null, capacity, p.PROT_READ|p.PROT_WRITE, | 96 | const addr = p.mmap(null, capacity, p.PROT_READ|p.PROT_WRITE, |
| 75 | p.MAP_PRIVATE|p.MAP_ANONYMOUS|p.MAP_NORESERVE, -1, 0); | 97 | p.MAP_PRIVATE|p.MAP_ANONYMOUS|p.MAP_NORESERVE, -1, 0); |
| 76 | if (addr == p.MAP_FAILED) { | 98 | if (addr == p.MAP_FAILED) { |
| 77 | return error.NoMem; | 99 | return error.OutOfMemory; |
| 78 | } | 100 | } |
| 79 | return IncrementingAllocator { | 101 | return IncrementingAllocator { |
| 80 | .allocator = Allocator { | 102 | .allocator = Allocator { |
| ... | @@ -132,7 +154,7 @@ pub const IncrementingAllocator = struct { | ... | @@ -132,7 +154,7 @@ pub const IncrementingAllocator = struct { |
| 132 | const adjusted_index = self.end_index + march_forward_bytes; | 154 | const adjusted_index = self.end_index + march_forward_bytes; |
| 133 | const new_end_index = adjusted_index + n; | 155 | const new_end_index = adjusted_index + n; |
| 134 | if (new_end_index > self.bytes.len) { | 156 | if (new_end_index > self.bytes.len) { |
| 135 | return error.NoMem; | 157 | return error.OutOfMemory; |
| 136 | } | 158 | } |
| 137 | const result = self.bytes[adjusted_index .. new_end_index]; | 159 | const result = self.bytes[adjusted_index .. new_end_index]; |
| 138 | self.end_index = new_end_index; | 160 | self.end_index = new_end_index; |
| ... | @@ -140,12 +162,16 @@ pub const IncrementingAllocator = struct { | ... | @@ -140,12 +162,16 @@ pub const IncrementingAllocator = struct { |
| 140 | } | 162 | } |
| 141 | 163 | ||
| 142 | fn realloc(allocator: &Allocator, old_mem: []u8, new_size: usize, alignment: usize) -> %[]u8 { | 164 | fn realloc(allocator: &Allocator, old_mem: []u8, new_size: usize, alignment: usize) -> %[]u8 { |
| 143 | const result = %return alloc(allocator, new_size, alignment); | 165 | if (new_size <= old_mem.len) { |
| 144 | copy(u8, result, old_mem); | 166 | return old_mem[0..new_size]; |
| 145 | return result; | 167 | } else { |
| 168 | const result = %return alloc(allocator, new_size, alignment); | ||
| 169 | copy(u8, result, old_mem); | ||
| 170 | return result; | ||
| 171 | } | ||
| 146 | } | 172 | } |
| 147 | 173 | ||
| 148 | fn free(allocator: &Allocator, bytes: &u8) { | 174 | fn free(allocator: &Allocator, bytes: []u8) { |
| 149 | // Do nothing. That's the point of an incrementing allocator. | 175 | // Do nothing. That's the point of an incrementing allocator. |
| 150 | } | 176 | } |
| 151 | }; | 177 | }; |
std/net.zig+2-2| ... | @@ -8,7 +8,7 @@ error Io; | ... | @@ -8,7 +8,7 @@ error Io; |
| 8 | error TimedOut; | 8 | error TimedOut; |
| 9 | error ConnectionReset; | 9 | error ConnectionReset; |
| 10 | error ConnectionRefused; | 10 | error ConnectionRefused; |
| 11 | error NoMem; | 11 | error OutOfMemory; |
| 12 | error NotSocket; | 12 | error NotSocket; |
| 13 | error BadFd; | 13 | error BadFd; |
| 14 | 14 | ||
| ... | @@ -38,7 +38,7 @@ const Connection = struct { | ... | @@ -38,7 +38,7 @@ const Connection = struct { |
| 38 | linux.EFAULT => unreachable, | 38 | linux.EFAULT => unreachable, |
| 39 | linux.ENOTSOCK => return error.NotSocket, | 39 | linux.ENOTSOCK => return error.NotSocket, |
| 40 | linux.EINTR => return error.SigInterrupt, | 40 | linux.EINTR => return error.SigInterrupt, |
| 41 | linux.ENOMEM => return error.NoMem, | 41 | linux.ENOMEM => return error.OutOfMemory, |
| 42 | linux.ECONNREFUSED => return error.ConnectionRefused, | 42 | linux.ECONNREFUSED => return error.ConnectionRefused, |
| 43 | linux.EBADF => return error.BadFd, | 43 | linux.EBADF => return error.BadFd, |
| 44 | // TODO more error values | 44 | // TODO more error values |
std/os/index.zig+8-3| ... | @@ -491,7 +491,7 @@ pub fn getCwd(allocator: &Allocator) -> %[]u8 { | ... | @@ -491,7 +491,7 @@ pub fn getCwd(allocator: &Allocator) -> %[]u8 { |
| 491 | continue; | 491 | continue; |
| 492 | } | 492 | } |
| 493 | 493 | ||
| 494 | return buf[0..result]; | 494 | return allocator.shrink(u8, buf, result); |
| 495 | } | 495 | } |
| 496 | }, | 496 | }, |
| 497 | else => { | 497 | else => { |
| ... | @@ -506,12 +506,17 @@ pub fn getCwd(allocator: &Allocator) -> %[]u8 { | ... | @@ -506,12 +506,17 @@ pub fn getCwd(allocator: &Allocator) -> %[]u8 { |
| 506 | return error.Unexpected; | 506 | return error.Unexpected; |
| 507 | } | 507 | } |
| 508 | 508 | ||
| 509 | return cstr.toSlice(buf.ptr); | 509 | return allocator.shrink(u8, buf, cstr.len(buf.ptr)); |
| 510 | } | 510 | } |
| 511 | }, | 511 | }, |
| 512 | } | 512 | } |
| 513 | } | 513 | } |
| 514 | 514 | ||
| 515 | test "os.getCwd" { | ||
| 516 | // at least call it so it gets compiled | ||
| 517 | _ = getCwd(&debug.global_allocator); | ||
| 518 | } | ||
| 519 | |||
| 515 | pub fn symLink(allocator: &Allocator, existing_path: []const u8, new_path: []const u8) -> %void { | 520 | pub fn symLink(allocator: &Allocator, existing_path: []const u8, new_path: []const u8) -> %void { |
| 516 | const full_buf = %return allocator.alloc(u8, existing_path.len + new_path.len + 2); | 521 | const full_buf = %return allocator.alloc(u8, existing_path.len + new_path.len + 2); |
| 517 | defer allocator.free(full_buf); | 522 | defer allocator.free(full_buf); |
| ... | @@ -988,7 +993,7 @@ pub fn readLink(allocator: &Allocator, pathname: []const u8) -> %[]u8 { | ... | @@ -988,7 +993,7 @@ pub fn readLink(allocator: &Allocator, pathname: []const u8) -> %[]u8 { |
| 988 | result_buf = %return allocator.realloc(u8, result_buf, result_buf.len * 2); | 993 | result_buf = %return allocator.realloc(u8, result_buf, result_buf.len * 2); |
| 989 | continue; | 994 | continue; |
| 990 | } | 995 | } |
| 991 | return result_buf[0..ret_val]; | 996 | return allocator.shrink(u8, result_buf, ret_val); |
| 992 | } | 997 | } |
| 993 | } | 998 | } |
| 994 | 999 |
std/os/path.zig+64-3| ... | @@ -6,8 +6,9 @@ const mem = @import("../mem.zig"); | ... | @@ -6,8 +6,9 @@ const mem = @import("../mem.zig"); |
| 6 | const fmt = @import("../fmt/index.zig"); | 6 | const fmt = @import("../fmt/index.zig"); |
| 7 | const Allocator = mem.Allocator; | 7 | const Allocator = mem.Allocator; |
| 8 | const os = @import("index.zig"); | 8 | const os = @import("index.zig"); |
| 9 | const math = @import("../math.zig"); | 9 | const math = @import("../math/index.zig"); |
| 10 | const posix = os.posix; | 10 | const posix = os.posix; |
| 11 | const windows = os.windows; | ||
| 11 | const c = @import("../c/index.zig"); | 12 | const c = @import("../c/index.zig"); |
| 12 | const cstr = @import("../cstr.zig"); | 13 | const cstr = @import("../cstr.zig"); |
| 13 | 14 | ||
| ... | @@ -921,7 +922,62 @@ error Unexpected; | ... | @@ -921,7 +922,62 @@ error Unexpected; |
| 921 | /// Caller must deallocate result. | 922 | /// Caller must deallocate result. |
| 922 | pub fn real(allocator: &Allocator, pathname: []const u8) -> %[]u8 { | 923 | pub fn real(allocator: &Allocator, pathname: []const u8) -> %[]u8 { |
| 923 | switch (builtin.os) { | 924 | switch (builtin.os) { |
| 924 | Os.windows => @compileError("TODO implement os.path.real for windows"), | 925 | Os.windows => { |
| 926 | const pathname_buf = %return allocator.alloc(u8, pathname.len + 1); | ||
| 927 | defer allocator.free(pathname_buf); | ||
| 928 | |||
| 929 | mem.copy(u8, pathname_buf, pathname); | ||
| 930 | pathname_buf[pathname.len] = 0; | ||
| 931 | |||
| 932 | const h_file = windows.CreateFileA(pathname_buf.ptr, | ||
| 933 | windows.GENERIC_READ, windows.FILE_SHARE_READ, null, windows.OPEN_EXISTING, | ||
| 934 | windows.FILE_ATTRIBUTE_NORMAL, null); | ||
| 935 | if (h_file == windows.INVALID_HANDLE_VALUE) { | ||
| 936 | const err = windows.GetLastError(); | ||
| 937 | return switch (err) { | ||
| 938 | windows.ERROR.FILE_NOT_FOUND => error.FileNotFound, | ||
| 939 | windows.ERROR.ACCESS_DENIED => error.AccessDenied, | ||
| 940 | windows.ERROR.FILENAME_EXCED_RANGE => error.NameTooLong, | ||
| 941 | else => error.Unexpected, | ||
| 942 | }; | ||
| 943 | } | ||
| 944 | defer assert(windows.CloseHandle(h_file)); | ||
| 945 | var buf = %return allocator.alloc(u8, 256); | ||
| 946 | %defer allocator.free(buf); | ||
| 947 | while (true) { | ||
| 948 | const buf_len = math.cast(windows.DWORD, buf.len) %% return error.NameTooLong; | ||
| 949 | const result = windows.GetFinalPathNameByHandleA(h_file, buf.ptr, buf_len, windows.VOLUME_NAME_DOS); | ||
| 950 | |||
| 951 | if (result == 0) { | ||
| 952 | const err = windows.GetLastError(); | ||
| 953 | return switch (err) { | ||
| 954 | windows.ERROR.PATH_NOT_FOUND => error.FileNotFound, | ||
| 955 | windows.ERROR.NOT_ENOUGH_MEMORY => error.OutOfMemory, | ||
| 956 | windows.ERROR.INVALID_PARAMETER => unreachable, | ||
| 957 | else => error.Unexpected, | ||
| 958 | }; | ||
| 959 | } | ||
| 960 | |||
| 961 | if (result > buf.len) { | ||
| 962 | buf = %return allocator.realloc(u8, buf, result); | ||
| 963 | continue; | ||
| 964 | } | ||
| 965 | |||
| 966 | // windows returns \\?\ prepended to the path | ||
| 967 | // we strip it because nobody wants \\?\ prepended to their path | ||
| 968 | const final_len = if (result > 4 and mem.startsWith(u8, buf, "\\\\?\\")) { | ||
| 969 | var i: usize = 4; | ||
| 970 | while (i < result) : (i += 1) { | ||
| 971 | buf[i - 4] = buf[i]; | ||
| 972 | } | ||
| 973 | result - 4 | ||
| 974 | } else { | ||
| 975 | result | ||
| 976 | }; | ||
| 977 | |||
| 978 | return allocator.shrink(u8, buf, final_len); | ||
| 979 | } | ||
| 980 | }, | ||
| 925 | Os.darwin, Os.macosx, Os.ios => { | 981 | Os.darwin, Os.macosx, Os.ios => { |
| 926 | // TODO instead of calling the libc function here, port the implementation | 982 | // TODO instead of calling the libc function here, port the implementation |
| 927 | // to Zig, and then remove the NameTooLong error possibility. | 983 | // to Zig, and then remove the NameTooLong error possibility. |
| ... | @@ -950,7 +1006,7 @@ pub fn real(allocator: &Allocator, pathname: []const u8) -> %[]u8 { | ... | @@ -950,7 +1006,7 @@ pub fn real(allocator: &Allocator, pathname: []const u8) -> %[]u8 { |
| 950 | else => error.Unexpected, | 1006 | else => error.Unexpected, |
| 951 | }; | 1007 | }; |
| 952 | } | 1008 | } |
| 953 | return cstr.toSlice(result_buf.ptr); | 1009 | return allocator.realloc(u8, result_buf, cstr.len(result_buf.ptr)); |
| 954 | }, | 1010 | }, |
| 955 | Os.linux => { | 1011 | Os.linux => { |
| 956 | const fd = %return os.posixOpen(pathname, posix.O_PATH|posix.O_NONBLOCK|posix.O_CLOEXEC, 0, allocator); | 1012 | const fd = %return os.posixOpen(pathname, posix.O_PATH|posix.O_NONBLOCK|posix.O_CLOEXEC, 0, allocator); |
| ... | @@ -964,3 +1020,8 @@ pub fn real(allocator: &Allocator, pathname: []const u8) -> %[]u8 { | ... | @@ -964,3 +1020,8 @@ pub fn real(allocator: &Allocator, pathname: []const u8) -> %[]u8 { |
| 964 | else => @compileError("TODO implement os.path.real for " ++ @enumTagName(builtin.os)), | 1020 | else => @compileError("TODO implement os.path.real for " ++ @enumTagName(builtin.os)), |
| 965 | } | 1021 | } |
| 966 | } | 1022 | } |
| 1023 | |||
| 1024 | test "os.path.real" { | ||
| 1025 | // at least call it so it gets compiled | ||
| 1026 | _ = real(&debug.global_allocator, "some_path"); | ||
| 1027 | } |
std/os/windows/index.zig+59| ... | @@ -1,5 +1,11 @@ | ... | @@ -1,5 +1,11 @@ |
| 1 | pub const ERROR = @import("error.zig"); | 1 | pub const ERROR = @import("error.zig"); |
| 2 | 2 | ||
| 3 | pub extern "kernel32" stdcallcc fn CloseHandle(hObject: HANDLE) -> BOOL; | ||
| 4 | |||
| 5 | pub extern "kernel32" stdcallcc fn CreateFileA(lpFileName: LPCSTR, dwDesiredAccess: DWORD, | ||
| 6 | dwShareMode: DWORD, lpSecurityAttributes: ?LPSECURITY_ATTRIBUTES, dwCreationDisposition: DWORD, | ||
| 7 | dwFlagsAndAttributes: DWORD, hTemplateFile: ?HANDLE) -> HANDLE; | ||
| 8 | |||
| 3 | pub extern "kernel32" stdcallcc fn CryptAcquireContext(phProv: &HCRYPTPROV, pszContainer: LPCTSTR, | 9 | pub extern "kernel32" stdcallcc fn CryptAcquireContext(phProv: &HCRYPTPROV, pszContainer: LPCTSTR, |
| 4 | pszProvider: LPCTSTR, dwProvType: DWORD, dwFlags: DWORD) -> bool; | 10 | pszProvider: LPCTSTR, dwProvType: DWORD, dwFlags: DWORD) -> bool; |
| 5 | 11 | ||
| ... | @@ -26,6 +32,9 @@ pub extern "kernel32" stdcallcc fn GetFileInformationByHandleEx(in_hFile: HANDLE | ... | @@ -26,6 +32,9 @@ pub extern "kernel32" stdcallcc fn GetFileInformationByHandleEx(in_hFile: HANDLE |
| 26 | in_FileInformationClass: FILE_INFO_BY_HANDLE_CLASS, out_lpFileInformation: &c_void, | 32 | in_FileInformationClass: FILE_INFO_BY_HANDLE_CLASS, out_lpFileInformation: &c_void, |
| 27 | in_dwBufferSize: DWORD) -> bool; | 33 | in_dwBufferSize: DWORD) -> bool; |
| 28 | 34 | ||
| 35 | pub extern "kernel32" stdcallcc fn GetFinalPathNameByHandleA(hFile: HANDLE, lpszFilePath: LPSTR, | ||
| 36 | cchFilePath: DWORD, dwFlags: DWORD) -> DWORD; | ||
| 37 | |||
| 29 | /// Retrieves a handle to the specified standard device (standard input, standard output, or standard error). | 38 | /// Retrieves a handle to the specified standard device (standard input, standard output, or standard error). |
| 30 | pub extern "kernel32" stdcallcc fn GetStdHandle(in_nStdHandle: DWORD) -> ?HANDLE; | 39 | pub extern "kernel32" stdcallcc fn GetStdHandle(in_nStdHandle: DWORD) -> ?HANDLE; |
| 31 | 40 | ||
| ... | @@ -131,3 +140,53 @@ pub const FILE_NAME_INFO = extern struct { | ... | @@ -131,3 +140,53 @@ pub const FILE_NAME_INFO = extern struct { |
| 131 | FileNameLength: DWORD, | 140 | FileNameLength: DWORD, |
| 132 | FileName: [1]WCHAR, | 141 | FileName: [1]WCHAR, |
| 133 | }; | 142 | }; |
| 143 | |||
| 144 | |||
| 145 | /// Return the normalized drive name. This is the default. | ||
| 146 | pub const FILE_NAME_NORMALIZED = 0x0; | ||
| 147 | /// Return the opened file name (not normalized). | ||
| 148 | pub const FILE_NAME_OPENED = 0x8; | ||
| 149 | |||
| 150 | /// Return the path with the drive letter. This is the default. | ||
| 151 | pub const VOLUME_NAME_DOS = 0x0; | ||
| 152 | /// Return the path with a volume GUID path instead of the drive name. | ||
| 153 | pub const VOLUME_NAME_GUID = 0x1; | ||
| 154 | /// Return the path with no drive information. | ||
| 155 | pub const VOLUME_NAME_NONE = 0x4; | ||
| 156 | /// Return the path with the volume device path. | ||
| 157 | pub const VOLUME_NAME_NT = 0x2; | ||
| 158 | |||
| 159 | |||
| 160 | pub const SECURITY_ATTRIBUTES = extern struct { | ||
| 161 | nLength: DWORD, | ||
| 162 | lpSecurityDescriptor: LPVOID, | ||
| 163 | bInheritHandle: BOOL, | ||
| 164 | }; | ||
| 165 | pub const PSECURITY_ATTRIBUTES = &SECURITY_ATTRIBUTES; | ||
| 166 | pub const LPSECURITY_ATTRIBUTES = &SECURITY_ATTRIBUTES; | ||
| 167 | |||
| 168 | |||
| 169 | pub const GENERIC_READ = 0x80000000; | ||
| 170 | pub const GENERIC_WRITE = 0x40000000; | ||
| 171 | pub const GENERIC_EXECUTE = 0x20000000; | ||
| 172 | pub const GENERIC_ALL = 0x10000000; | ||
| 173 | |||
| 174 | pub const FILE_SHARE_DELETE = 0x00000004; | ||
| 175 | pub const FILE_SHARE_READ = 0x00000001; | ||
| 176 | pub const FILE_SHARE_WRITE = 0x00000002; | ||
| 177 | |||
| 178 | pub const CREATE_ALWAYS = 2; | ||
| 179 | pub const CREATE_NEW = 1; | ||
| 180 | pub const OPEN_ALWAYS = 4; | ||
| 181 | pub const OPEN_EXISTING = 3; | ||
| 182 | pub const TRUNCATE_EXISTING = 5; | ||
| 183 | |||
| 184 | |||
| 185 | pub const FILE_ATTRIBUTE_ARCHIVE = 0x20; | ||
| 186 | pub const FILE_ATTRIBUTE_ENCRYPTED = 0x4000; | ||
| 187 | pub const FILE_ATTRIBUTE_HIDDEN = 0x2; | ||
| 188 | pub const FILE_ATTRIBUTE_NORMAL = 0x80; | ||
| 189 | pub const FILE_ATTRIBUTE_OFFLINE = 0x1000; | ||
| 190 | pub const FILE_ATTRIBUTE_READONLY = 0x1; | ||
| 191 | pub const FILE_ATTRIBUTE_SYSTEM = 0x4; | ||
| 192 | pub const FILE_ATTRIBUTE_TEMPORARY = 0x100; |