Skip to content

Misc windows additions+fixes #3715

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Dec 2, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/std/child_process.zig
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ pub const ChildProcess = struct {
}

fn waitUnwrappedWindows(self: *ChildProcess) !void {
const result = windows.WaitForSingleObject(self.handle, windows.INFINITE);
const result = windows.WaitForSingleObjectEx(self.handle, windows.INFINITE, false);

self.term = @as(SpawnError!Term, x: {
var exit_code: windows.DWORD = undefined;
Expand Down
128 changes: 56 additions & 72 deletions lib/std/os/bits/windows.zig
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// The reference for these types and values is Microsoft Windows's ucrt (Universal C RunTime).

usingnamespace @import("../windows/bits.zig");
const ws2_32 = @import("../windows/ws2_32.zig");

pub const fd_t = HANDLE;
pub const pid_t = HANDLE;
Expand Down Expand Up @@ -163,80 +164,63 @@ pub const F_OK = 0;
pub const AT_REMOVEDIR = 0x200;

pub const in_port_t = u16;
pub const sa_family_t = u16;
pub const sa_family_t = ws2_32.ADDRESS_FAMILY;
pub const socklen_t = u32;

pub const sockaddr = extern struct {
family: sa_family_t,
data: [14]u8,
};
pub const sockaddr_in = extern struct {
family: sa_family_t = AF_INET,
port: in_port_t,
addr: in_addr,
zero: [8]u8 = [8]u8{ 0, 0, 0, 0, 0, 0, 0, 0 },
};
pub const sockaddr_in6 = extern struct {
family: sa_family_t = AF_INET6,
port: in_port_t,
flowinfo: u32,
addr: in6_addr,
scope_id: u32,
};
pub const sockaddr = ws2_32.sockaddr;
pub const sockaddr_in = ws2_32.sockaddr_in;
pub const sockaddr_in6 = ws2_32.sockaddr_in6;
pub const sockaddr_un = ws2_32.sockaddr_un;

pub const in6_addr = [16]u8;
pub const in_addr = u32;

pub const sockaddr_un = extern struct {
family: sa_family_t = AF_UNIX,
path: [108]u8,
};

pub const AF_UNSPEC = 0;
pub const AF_UNIX = 1;
pub const AF_INET = 2;
pub const AF_IMPLINK = 3;
pub const AF_PUP = 4;
pub const AF_CHAOS = 5;
pub const AF_NS = 6;
pub const AF_IPX = AF_NS;
pub const AF_ISO = 7;
pub const AF_OSI = AF_ISO;
pub const AF_ECMA = 8;
pub const AF_DATAKIT = 9;
pub const AF_CCITT = 10;
pub const AF_SNA = 11;
pub const AF_DECnet = 12;
pub const AF_DLI = 13;
pub const AF_LAT = 14;
pub const AF_HYLINK = 15;
pub const AF_APPLETALK = 16;
pub const AF_NETBIOS = 17;
pub const AF_VOICEVIEW = 18;
pub const AF_FIREFOX = 19;
pub const AF_UNKNOWN1 = 20;
pub const AF_BAN = 21;
pub const AF_ATM = 22;
pub const AF_INET6 = 23;
pub const AF_CLUSTER = 24;
pub const AF_12844 = 25;
pub const AF_IRDA = 26;
pub const AF_NETDES = 28;
pub const AF_TCNPROCESS = 29;
pub const AF_TCNMESSAGE = 30;
pub const AF_ICLFXBM = 31;
pub const AF_BTH = 32;
pub const AF_MAX = 33;

pub const SOCK_STREAM = 1;
pub const SOCK_DGRAM = 2;
pub const SOCK_RAW = 3;
pub const SOCK_RDM = 4;
pub const SOCK_SEQPACKET = 5;

pub const IPPROTO_ICMP = 1;
pub const IPPROTO_IGMP = 2;
pub const BTHPROTO_RFCOMM = 3;
pub const IPPROTO_TCP = 6;
pub const IPPROTO_UDP = 17;
pub const IPPROTO_ICMPV6 = 58;
pub const IPPROTO_RM = 113;
pub const AF_UNSPEC = ws2_32.AF_UNSPEC;
pub const AF_UNIX = ws2_32.AF_UNIX;
pub const AF_INET = ws2_32.AF_INET;
pub const AF_IMPLINK = ws2_32.AF_IMPLINK;
pub const AF_PUP = ws2_32.AF_PUP;
pub const AF_CHAOS = ws2_32.AF_CHAOS;
pub const AF_NS = ws2_32.AF_NS;
pub const AF_IPX = ws2_32.AF_IPX;
pub const AF_ISO = ws2_32.AF_ISO;
pub const AF_OSI = ws2_32.AF_OSI;
pub const AF_ECMA = ws2_32.AF_ECMA;
pub const AF_DATAKIT = ws2_32.AF_DATAKIT;
pub const AF_CCITT = ws2_32.AF_CCITT;
pub const AF_SNA = ws2_32.AF_SNA;
pub const AF_DECnet = ws2_32.AF_DECnet;
pub const AF_DLI = ws2_32.AF_DLI;
pub const AF_LAT = ws2_32.AF_LAT;
pub const AF_HYLINK = ws2_32.AF_HYLINK;
pub const AF_APPLETALK = ws2_32.AF_APPLETALK;
pub const AF_NETBIOS = ws2_32.AF_NETBIOS;
pub const AF_VOICEVIEW = ws2_32.AF_VOICEVIEW;
pub const AF_FIREFOX = ws2_32.AF_FIREFOX;
pub const AF_UNKNOWN1 = ws2_32.AF_UNKNOWN1;
pub const AF_BAN = ws2_32.AF_BAN;
pub const AF_ATM = ws2_32.AF_ATM;
pub const AF_INET6 = ws2_32.AF_INET6;
pub const AF_CLUSTER = ws2_32.AF_CLUSTER;
pub const AF_12844 = ws2_32.AF_12844;
pub const AF_IRDA = ws2_32.AF_IRDA;
pub const AF_NETDES = ws2_32.AF_NETDES;
pub const AF_TCNPROCESS = ws2_32.AF_TCNPROCESS;
pub const AF_TCNMESSAGE = ws2_32.AF_TCNMESSAGE;
pub const AF_ICLFXBM = ws2_32.AF_ICLFXBM;
pub const AF_BTH = ws2_32.AF_BTH;
pub const AF_MAX = ws2_32.AF_MAX;

pub const SOCK_STREAM = ws2_32.SOCK_STREAM;
pub const SOCK_DGRAM = ws2_32.SOCK_DGRAM;
pub const SOCK_RAW = ws2_32.SOCK_RAW;
pub const SOCK_RDM = ws2_32.SOCK_RDM;
pub const SOCK_SEQPACKET = ws2_32.SOCK_SEQPACKET;

pub const IPPROTO_ICMP = ws2_32.IPPROTO_ICMP;
pub const IPPROTO_IGMP = ws2_32.IPPROTO_IGMP;
pub const BTHPROTO_RFCOMM = ws2_32.BTHPROTO_RFCOMM;
pub const IPPROTO_TCP = ws2_32.IPPROTO_TCP;
pub const IPPROTO_UDP = ws2_32.IPPROTO_UDP;
pub const IPPROTO_ICMPV6 = ws2_32.IPPROTO_ICMPV6;
pub const IPPROTO_RM = ws2_32.IPPROTO_RM;
65 changes: 60 additions & 5 deletions lib/std/os/windows.zig
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,22 @@ pub fn CreatePipe(rd: *HANDLE, wr: *HANDLE, sattr: *const SECURITY_ATTRIBUTES) C
}
}

pub fn CreateEventEx(attributes: ?*SECURITY_ATTRIBUTES, name: []const u8, flags: DWORD, desired_access: DWORD) !HANDLE {
const nameW = try sliceToPrefixedFileW(name);
return CreateEventExW(attributes, &nameW, flags, desired_access);
}

pub fn CreateEventExW(attributes: ?*SECURITY_ATTRIBUTES, nameW: [*:0]const u16, flags: DWORD, desired_access: DWORD) !HANDLE {
const handle = kernel32.CreateEventExW(attributes, nameW, flags, desired_access);
if (handle) |h| {
return h;
} else {
switch (kernel32.GetLastError()) {
else => |err| return unexpectedError(err),
}
}
}

pub fn DeviceIoControl(
h: HANDLE,
ioControlCode: DWORD,
Expand All @@ -116,6 +132,7 @@ pub fn DeviceIoControl(
overlapped,
) == 0) {
switch (kernel32.GetLastError()) {
ERROR.IO_PENDING => if (overlapped == null) unreachable,
else => |err| return unexpectedError(err),
}
}
Expand All @@ -124,9 +141,9 @@ pub fn DeviceIoControl(

pub fn GetOverlappedResult(h: HANDLE, overlapped: *OVERLAPPED, wait: bool) !DWORD {
var bytes: DWORD = undefined;
if (kernel32.GetOverlappedResult(h, overlapped, &bytes, wait) == 0) {
if (kernel32.GetOverlappedResult(h, overlapped, &bytes, @boolToInt(wait)) == 0) {
switch (kernel32.GetLastError()) {
ERROR_IO_INCOMPLETE => if (!wait) return error.WouldBlock else unreachable,
ERROR.IO_INCOMPLETE => if (!wait) return error.WouldBlock else unreachable,
else => |err| return unexpectedError(err),
}
}
Expand Down Expand Up @@ -171,8 +188,8 @@ pub const WaitForSingleObjectError = error{
Unexpected,
};

pub fn WaitForSingleObject(handle: HANDLE, milliseconds: DWORD) WaitForSingleObjectError!void {
switch (kernel32.WaitForSingleObject(handle, milliseconds)) {
pub fn WaitForSingleObjectEx(handle: HANDLE, milliseconds: DWORD, alertable: bool) WaitForSingleObjectError!void {
switch (kernel32.WaitForSingleObjectEx(handle, milliseconds, @boolToInt(alertable))) {
WAIT_ABANDONED => return error.WaitAbandoned,
WAIT_OBJECT_0 => return,
WAIT_TIMEOUT => return error.WaitTimeOut,
Expand All @@ -183,6 +200,34 @@ pub fn WaitForSingleObject(handle: HANDLE, milliseconds: DWORD) WaitForSingleObj
}
}

pub fn WaitForMultipleObjectsEx(handles: []const HANDLE, waitAll: bool, milliseconds: DWORD, alertable: bool) !u32 {
assert(handles.len < MAXIMUM_WAIT_OBJECTS);
const nCount: DWORD = @intCast(DWORD, handles.len);
switch (kernel32.WaitForMultipleObjectsEx(
nCount,
handles.ptr,
@boolToInt(waitAll),
milliseconds,
@boolToInt(alertable),
)) {
WAIT_OBJECT_0...WAIT_OBJECT_0 + MAXIMUM_WAIT_OBJECTS => |n| {
const handle_index = n - WAIT_OBJECT_0;
assert(handle_index < nCount);
return handle_index;
},
WAIT_ABANDONED_0...WAIT_ABANDONED_0 + MAXIMUM_WAIT_OBJECTS => |n| {
const handle_index = n - WAIT_ABANDONED_0;
assert(handle_index < nCount);
return error.WaitAbandoned;
},
WAIT_TIMEOUT => return error.WaitTimeOut,
WAIT_FAILED => switch (kernel32.GetLastError()) {
else => |err| return unexpectedError(err),
},
else => return error.Unexpected,
}
}

pub const FindFirstFileError = error{
FileNotFound,
InvalidUtf8,
Expand Down Expand Up @@ -647,13 +692,23 @@ pub fn WSASocketW(
return rc;
}

pub fn closesocket(s: ws2_32.SOCKET) !void {
switch (ws2_32.closesocket(s)) {
0 => {},
ws2_32.SOCKET_ERROR => switch (ws2_32.WSAGetLastError()) {
else => |err| return unexpectedWSAError(err),
},
else => unreachable,
}
}

pub fn WSAIoctl(
s: ws2_32.SOCKET,
dwIoControlCode: DWORD,
inBuffer: ?[]const u8,
outBuffer: []u8,
overlapped: ?*ws2_32.WSAOVERLAPPED,
completionRoutine: ?*ws2_32.WSAOVERLAPPED_COMPLETION_ROUTINE,
completionRoutine: ?ws2_32.WSAOVERLAPPED_COMPLETION_ROUTINE,
) !DWORD {
var bytes: DWORD = undefined;
switch (ws2_32.WSAIoctl(
Expand Down
19 changes: 17 additions & 2 deletions lib/std/os/windows/bits.zig
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ pub const STD_OUTPUT_HANDLE = maxInt(DWORD) - 11 + 1;
/// The standard error device. Initially, this is the active console screen buffer, CONOUT$.
pub const STD_ERROR_HANDLE = maxInt(DWORD) - 12 + 1;

pub const SHORT = c_short;
pub const BOOL = c_int;
pub const BOOLEAN = BYTE;
pub const BYTE = u8;
Expand Down Expand Up @@ -54,6 +53,8 @@ pub const UNICODE = false;
pub const WCHAR = u16;
pub const WORD = u16;
pub const LARGE_INTEGER = i64;
pub const USHORT = u16;
pub const SHORT = i16;
pub const ULONG = u32;
pub const LONG = i32;
pub const ULONGLONG = u64;
Expand Down Expand Up @@ -236,7 +237,11 @@ pub const FILE_NAME_INFORMATION = extern struct {
};

pub const IO_STATUS_BLOCK = extern struct {
Status: usize,
// "DUMMYUNIONNAME" expands to "u"
u: extern union {
Status: NTSTATUS,
Pointer: ?*c_void,
},
Information: ULONG_PTR,
};

Expand Down Expand Up @@ -489,6 +494,13 @@ pub const FILE_ATTRIBUTE_SYSTEM = 0x4;
pub const FILE_ATTRIBUTE_TEMPORARY = 0x100;
pub const FILE_ATTRIBUTE_VIRTUAL = 0x10000;

// flags for CreateEvent
pub const CREATE_EVENT_INITIAL_SET = 0x00000002;
pub const CREATE_EVENT_MANUAL_RESET = 0x00000001;

pub const EVENT_ALL_ACCESS = 0x1F0003;
pub const EVENT_MODIFY_STATE = 0x0002;

pub const PROCESS_INFORMATION = extern struct {
hProcess: HANDLE,
hThread: HANDLE,
Expand Down Expand Up @@ -534,7 +546,10 @@ pub const STARTF_USESTDHANDLES = 0x00000100;

pub const INFINITE = 4294967295;

pub const MAXIMUM_WAIT_OBJECTS = 64;

pub const WAIT_ABANDONED = 0x00000080;
pub const WAIT_ABANDONED_0 = WAIT_ABANDONED + 0;
pub const WAIT_OBJECT_0 = 0x00000000;
pub const WAIT_TIMEOUT = 0x00000102;
pub const WAIT_FAILED = 0xFFFFFFFF;
Expand Down
21 changes: 20 additions & 1 deletion lib/std/os/windows/kernel32.zig
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ pub extern "kernel32" stdcallcc fn CloseHandle(hObject: HANDLE) BOOL;

pub extern "kernel32" stdcallcc fn CreateDirectoryW(lpPathName: [*]const u16, lpSecurityAttributes: ?*SECURITY_ATTRIBUTES) BOOL;

pub extern "kernel32" stdcallcc fn CreateEventExW(
lpEventAttributes: ?*SECURITY_ATTRIBUTES,
lpName: [*:0]const u16,
dwFlags: DWORD,
dwDesiredAccess: DWORD,
) ?HANDLE;

pub extern "kernel32" stdcallcc fn CreateFileW(
lpFileName: [*]const u16, // TODO null terminated pointer type
dwDesiredAccess: DWORD,
Expand Down Expand Up @@ -52,7 +59,7 @@ pub extern "kernel32" stdcallcc fn DeviceIoControl(
nInBufferSize: DWORD,
lpOutBuffer: ?LPVOID,
nOutBufferSize: DWORD,
lpBytesReturned: LPDWORD,
lpBytesReturned: ?*DWORD,
lpOverlapped: ?*OVERLAPPED,
) BOOL;

Expand Down Expand Up @@ -205,6 +212,18 @@ pub extern "kernel32" stdcallcc fn TlsFree(dwTlsIndex: DWORD) BOOL;

pub extern "kernel32" stdcallcc fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) DWORD;

pub extern "kernel32" stdcallcc fn WaitForSingleObjectEx(hHandle: HANDLE, dwMilliseconds: DWORD, bAlertable: BOOL) DWORD;

pub extern "kernel32" stdcallcc fn WaitForMultipleObjects(nCount: DWORD, lpHandle: [*]const HANDLE, bWaitAll:BOOL, dwMilliseconds: DWORD) DWORD;

pub extern "kernel32" stdcallcc fn WaitForMultipleObjectsEx(
nCount: DWORD,
lpHandle: [*]const HANDLE,
bWaitAll:BOOL,
dwMilliseconds: DWORD,
bAlertable: BOOL,
) DWORD;

pub extern "kernel32" stdcallcc fn WriteFile(
in_hFile: HANDLE,
in_lpBuffer: [*]const u8,
Expand Down
4 changes: 2 additions & 2 deletions lib/std/os/windows/ntdll.zig
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ pub extern "NtDll" stdcallcc fn NtCreateFile(
pub extern "NtDll" stdcallcc fn NtDeviceIoControlFile(
FileHandle: HANDLE,
Event: ?HANDLE,
ApcRoutine: ?*IO_APC_ROUTINE,
ApcContext: usize,
ApcRoutine: ?IO_APC_ROUTINE,
ApcContext: ?*c_void,
IoStatusBlock: *IO_STATUS_BLOCK,
IoControlCode: ULONG,
InputBuffer: ?*const c_void,
Expand Down
7 changes: 7 additions & 0 deletions lib/std/os/windows/status.zig
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,13 @@ pub const ABANDONED_WAIT_0 = 0x00000080;
pub const ABANDONED_WAIT_63 = 0x000000BF;
pub const USER_APC = 0x000000C0;
pub const ALERTED = 0x00000101;

/// The given Timeout interval expired.
pub const TIMEOUT = 0x00000102;

/// The operation that was requested is pending completion.
pub const PENDING = 0x00000103;

pub const REPARSE = 0x00000104;
pub const MORE_ENTRIES = 0x00000105;
pub const NOT_ALL_ASSIGNED = 0x00000106;
Expand Down Expand Up @@ -128,6 +133,8 @@ pub const GUARD_PAGE_VIOLATION = 0x80000001;
pub const DATATYPE_MISALIGNMENT = 0x80000002;
pub const BREAKPOINT = 0x80000003;
pub const SINGLE_STEP = 0x80000004;

/// The data was too large to fit into the specified buffer.
pub const BUFFER_OVERFLOW = 0x80000005;
pub const NO_MORE_FILES = 0x80000006;
pub const WAKE_SYSTEM_DEBUGGER = 0x80000007;
Expand Down
Loading