diff options
| author | Andrea Orru <andrea@orru.io> | 2018-08-06 01:43:19 -0400 |
|---|---|---|
| committer | Andrea Orru <andrea@orru.io> | 2018-08-06 01:43:19 -0400 |
| commit | d2f5e57b68da0b16e5789ca19045ccbcb4ecfa8d (patch) | |
| tree | e9fa3caec533a0d1e2b434868b2fde1f9240e5c8 /std/os/windows/util.zig | |
| parent | 06614b3fa09954464c2e2f32756cacedc178a282 (diff) | |
| parent | 63a23e848a62d5f167f8d5478de9766cb24aa6eb (diff) | |
| download | zig-d2f5e57b68da0b16e5789ca19045ccbcb4ecfa8d.tar.gz zig-d2f5e57b68da0b16e5789ca19045ccbcb4ecfa8d.zip | |
Merge branch 'master' into zen_stdlib
Diffstat (limited to 'std/os/windows/util.zig')
| -rw-r--r-- | std/os/windows/util.zig | 135 |
1 files changed, 110 insertions, 25 deletions
diff --git a/std/os/windows/util.zig b/std/os/windows/util.zig index 5af318b7b0..c9d2c3c3e6 100644 --- a/std/os/windows/util.zig +++ b/std/os/windows/util.zig @@ -7,7 +7,7 @@ const mem = std.mem; const BufMap = std.BufMap; const cstr = std.cstr; -pub const WaitError = error { +pub const WaitError = error{ WaitAbandoned, WaitTimeOut, Unexpected, @@ -33,7 +33,7 @@ pub fn windowsClose(handle: windows.HANDLE) void { assert(windows.CloseHandle(handle) != 0); } -pub const WriteError = error { +pub const WriteError = error{ SystemResources, OperationAborted, IoPending, @@ -42,7 +42,7 @@ pub const WriteError = error { }; pub fn windowsWrite(handle: windows.HANDLE, bytes: []const u8) WriteError!void { - if (windows.WriteFile(handle, @ptrCast(&const c_void, bytes.ptr), u32(bytes.len), null, null) == 0) { + if (windows.WriteFile(handle, @ptrCast(*const c_void, bytes.ptr), @intCast(u32, bytes.len), null, null) == 0) { const err = windows.GetLastError(); return switch (err) { windows.ERROR.INVALID_USER_BUFFER => WriteError.SystemResources, @@ -68,20 +68,23 @@ 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)) == 0) - { + if (windows.GetFileInformationByHandleEx( + handle, + windows.FileNameInfo, + @ptrCast(*c_void, &name_info_bytes[0]), + @intCast(u32, name_info_bytes.len), + ) == 0) { 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; + 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 = @bytesToSlice(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; } -pub const OpenError = error { +pub const OpenError = error{ SharingViolation, PathAlreadyExists, FileNotFound, @@ -92,15 +95,18 @@ pub const OpenError = error { }; /// `file_path` needs to be copied in memory to add a null terminating byte, hence the allocator. -pub fn windowsOpen(allocator: &mem.Allocator, file_path: []const u8, desired_access: windows.DWORD, share_mode: windows.DWORD, - creation_disposition: windows.DWORD, flags_and_attrs: windows.DWORD) - OpenError!windows.HANDLE -{ +pub fn windowsOpen( + allocator: *mem.Allocator, + file_path: []const u8, + desired_access: windows.DWORD, + share_mode: windows.DWORD, + creation_disposition: windows.DWORD, + flags_and_attrs: windows.DWORD, +) OpenError!windows.HANDLE { const path_with_null = try cstr.addNullByte(allocator, file_path); defer allocator.free(path_with_null); - const result = windows.CreateFileA(path_with_null.ptr, desired_access, share_mode, null, creation_disposition, - flags_and_attrs, null); + const result = windows.CreateFileA(path_with_null.ptr, desired_access, share_mode, null, creation_disposition, flags_and_attrs, null); if (result == windows.INVALID_HANDLE_VALUE) { const err = windows.GetLastError(); @@ -118,7 +124,7 @@ pub fn windowsOpen(allocator: &mem.Allocator, file_path: []const u8, desired_acc } /// Caller must free result. -pub fn createWindowsEnvBlock(allocator: &mem.Allocator, env_map: &const BufMap) ![]u8 { +pub fn createWindowsEnvBlock(allocator: *mem.Allocator, env_map: *const BufMap) ![]u8 { // count bytes needed const bytes_needed = x: { var bytes_needed: usize = 1; // 1 for the final null byte @@ -149,25 +155,104 @@ pub fn createWindowsEnvBlock(allocator: &mem.Allocator, env_map: &const BufMap) return result; } -pub fn windowsLoadDll(allocator: &mem.Allocator, dll_path: []const u8) !windows.HMODULE { +pub fn windowsLoadDll(allocator: *mem.Allocator, dll_path: []const u8) !windows.HMODULE { const padded_buff = try cstr.addNullByte(allocator, dll_path); defer allocator.free(padded_buff); - return windows.LoadLibraryA(padded_buff.ptr) ?? error.DllNotFound; + return windows.LoadLibraryA(padded_buff.ptr) orelse error.DllNotFound; } pub fn windowsUnloadDll(hModule: windows.HMODULE) void { - assert(windows.FreeLibrary(hModule)!= 0); + assert(windows.FreeLibrary(hModule) != 0); } - test "InvalidDll" { - if (builtin.os != builtin.Os.windows) return; + if (builtin.os != builtin.Os.windows) return error.SkipZigTest; const DllName = "asdf.dll"; const allocator = std.debug.global_allocator; - const handle = os.windowsLoadDll(allocator, DllName) catch |err| { + const handle = os.windowsLoadDll(allocator, DllName) catch |err| { assert(err == error.DllNotFound); return; }; } +pub fn windowsFindFirstFile( + allocator: *mem.Allocator, + dir_path: []const u8, + find_file_data: *windows.WIN32_FIND_DATAA, +) !windows.HANDLE { + const wild_and_null = []u8{ '\\', '*', 0 }; + const path_with_wild_and_null = try allocator.alloc(u8, dir_path.len + wild_and_null.len); + defer allocator.free(path_with_wild_and_null); + + mem.copy(u8, path_with_wild_and_null, dir_path); + mem.copy(u8, path_with_wild_and_null[dir_path.len..], wild_and_null); + + const handle = windows.FindFirstFileA(path_with_wild_and_null.ptr, find_file_data); + + if (handle == windows.INVALID_HANDLE_VALUE) { + const err = windows.GetLastError(); + switch (err) { + windows.ERROR.FILE_NOT_FOUND, + windows.ERROR.PATH_NOT_FOUND, + => return error.PathNotFound, + else => return os.unexpectedErrorWindows(err), + } + } + + return handle; +} + +/// Returns `true` if there was another file, `false` otherwise. +pub fn windowsFindNextFile(handle: windows.HANDLE, find_file_data: *windows.WIN32_FIND_DATAA) !bool { + if (windows.FindNextFileA(handle, find_file_data) == 0) { + const err = windows.GetLastError(); + return switch (err) { + windows.ERROR.NO_MORE_FILES => false, + else => os.unexpectedErrorWindows(err), + }; + } + return true; +} + +pub const WindowsCreateIoCompletionPortError = error{Unexpected}; + +pub fn windowsCreateIoCompletionPort(file_handle: windows.HANDLE, existing_completion_port: ?windows.HANDLE, completion_key: usize, concurrent_thread_count: windows.DWORD) !windows.HANDLE { + const handle = windows.CreateIoCompletionPort(file_handle, existing_completion_port, completion_key, concurrent_thread_count) orelse { + const err = windows.GetLastError(); + switch (err) { + else => return os.unexpectedErrorWindows(err), + } + }; + return handle; +} + +pub const WindowsPostQueuedCompletionStatusError = error{Unexpected}; + +pub fn windowsPostQueuedCompletionStatus(completion_port: windows.HANDLE, bytes_transferred_count: windows.DWORD, completion_key: usize, lpOverlapped: ?*windows.OVERLAPPED) WindowsPostQueuedCompletionStatusError!void { + if (windows.PostQueuedCompletionStatus(completion_port, bytes_transferred_count, completion_key, lpOverlapped) == 0) { + const err = windows.GetLastError(); + switch (err) { + else => return os.unexpectedErrorWindows(err), + } + } +} + +pub const WindowsWaitResult = error{ + Normal, + Aborted, +}; + +pub fn windowsGetQueuedCompletionStatus(completion_port: windows.HANDLE, bytes_transferred_count: *windows.DWORD, lpCompletionKey: *usize, lpOverlapped: *?*windows.OVERLAPPED, dwMilliseconds: windows.DWORD) WindowsWaitResult { + if (windows.GetQueuedCompletionStatus(completion_port, bytes_transferred_count, lpCompletionKey, lpOverlapped, dwMilliseconds) == windows.FALSE) { + if (std.debug.runtime_safety) { + const err = windows.GetLastError(); + if (err != windows.ERROR.ABANDONED_WAIT_0) { + std.debug.warn("err: {}\n", err); + } + assert(err == windows.ERROR.ABANDONED_WAIT_0); + } + return WindowsWaitResult.Aborted; + } + return WindowsWaitResult.Normal; +} |
