-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
121 additions
and
109 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
const std = @import("../../index.zig"); | ||
const windows = std.os.windows; | ||
const assert = std.debug.assert; | ||
const mem = std.mem; | ||
|
||
error WaitAbandoned; | ||
error WaitTimeOut; | ||
|
||
pub fn windowsWaitSingle(handle: windows.HANDLE, milliseconds: windows.DWORD) -> %void { | ||
const result = windows.WaitForSingleObject(handle, milliseconds); | ||
return switch (result) { | ||
windows.WAIT_ABANDONED => error.WaitAbandoned, | ||
windows.WAIT_OBJECT_0 => {}, | ||
windows.WAIT_TIMEOUT => error.WaitTimeOut, | ||
windows.WAIT_FAILED => switch (windows.GetLastError()) { | ||
else => error.Unexpected, | ||
}, | ||
else => error.Unexpected, | ||
}; | ||
} | ||
|
||
pub fn windowsClose(handle: windows.HANDLE) { | ||
assert(windows.CloseHandle(handle)); | ||
} | ||
|
||
error SystemResources; | ||
error OperationAborted; | ||
error IoPending; | ||
error BrokenPipe; | ||
|
||
pub fn windowsWrite(handle: windows.HANDLE, bytes: []const u8) -> %void { | ||
if (!windows.WriteFile(handle, @ptrCast(&const c_void, bytes.ptr), u32(bytes.len), null, null)) { | ||
return switch (windows.GetLastError()) { | ||
windows.ERROR.INVALID_USER_BUFFER => error.SystemResources, | ||
windows.ERROR.NOT_ENOUGH_MEMORY => error.SystemResources, | ||
windows.ERROR.OPERATION_ABORTED => error.OperationAborted, | ||
windows.ERROR.NOT_ENOUGH_QUOTA => error.SystemResources, | ||
windows.ERROR.IO_PENDING => error.IoPending, | ||
windows.ERROR.BROKEN_PIPE => error.BrokenPipe, | ||
else => error.Unexpected, | ||
}; | ||
} | ||
} | ||
|
||
pub fn windowsIsTty(handle: windows.HANDLE) -> bool { | ||
if (windowsIsCygwinPty(handle)) | ||
return true; | ||
|
||
var out: windows.DWORD = undefined; | ||
return windows.GetConsoleMode(handle, &out); | ||
} | ||
|
||
pub fn windowsIsCygwinPty(handle: windows.HANDLE) -> bool { | ||
const size = @sizeOf(windows.FILE_NAME_INFO); | ||
var name_info_bytes align(@alignOf(windows.FILE_NAME_INFO)) = []u8{0} ** (size + windows.MAX_PATH); | ||
|
||
if (!windows.GetFileInformationByHandleEx(handle, windows.FileNameInfo, | ||
@ptrCast(&c_void, &name_info_bytes[0]), u32(name_info_bytes.len))) | ||
{ | ||
return true; | ||
} | ||
|
||
const name_info = @ptrCast(&const windows.FILE_NAME_INFO, &name_info_bytes[0]); | ||
const name_bytes = name_info_bytes[size..size + usize(name_info.FileNameLength)]; | ||
const name_wide = ([]u16)(name_bytes); | ||
return mem.indexOf(u16, name_wide, []u16{'m','s','y','s','-'}) != null or | ||
mem.indexOf(u16, name_wide, []u16{'-','p','t','y'}) != null; | ||
} | ||
|
||
error SharingViolation; | ||
error PipeBusy; | ||
|
||
/// `file_path` may need to be copied in memory to add a null terminating byte. In this case | ||
/// a fixed size buffer of size ::max_noalloc_path_len is an attempted solution. If the fixed | ||
/// size buffer is too small, and the provided allocator is null, ::error.NameTooLong is returned. | ||
/// otherwise if the fixed size buffer is too small, allocator is used to obtain the needed memory. | ||
pub fn windowsOpen(file_path: []const u8, desired_access: windows.DWORD, share_mode: windows.DWORD, | ||
creation_disposition: windows.DWORD, flags_and_attrs: windows.DWORD, allocator: ?&Allocator) -> %windows.HANDLE | ||
{ | ||
var stack_buf: [max_noalloc_path_len]u8 = undefined; | ||
var path0: []u8 = undefined; | ||
var need_free = false; | ||
defer if (need_free) (??allocator).free(path0); | ||
|
||
if (file_path.len < stack_buf.len) { | ||
path0 = stack_buf[0..file_path.len + 1]; | ||
} else if (allocator) |a| { | ||
path0 = %return a.alloc(u8, file_path.len + 1); | ||
need_free = true; | ||
} else { | ||
return error.NameTooLong; | ||
} | ||
mem.copy(u8, path0, file_path); | ||
path0[file_path.len] = 0; | ||
|
||
const result = windows.CreateFileA(path0.ptr, desired_access, share_mode, null, creation_disposition, | ||
flags_and_attrs, null); | ||
|
||
if (result == windows.INVALID_HANDLE_VALUE) { | ||
const err = windows.GetLastError(); | ||
return switch (err) { | ||
windows.ERROR.SHARING_VIOLATION => error.SharingViolation, | ||
windows.ERROR.ALREADY_EXISTS, windows.ERROR.FILE_EXISTS => error.PathAlreadyExists, | ||
windows.ERROR.FILE_NOT_FOUND => error.FileNotFound, | ||
windows.ERROR.ACCESS_DENIED => error.AccessDenied, | ||
windows.ERROR.PIPE_BUSY => error.PipeBusy, | ||
else => error.Unexpected, | ||
}; | ||
} | ||
|
||
return result; | ||
} |