NTSTATUS=0xc000000d INVALID_PARAMETER error when receving messages on windows 10

When calling operate with .net_receive on windows with either a unix socket or ipv4 on localhost I get the following error:

PS C:\Users\ab\Desktop\testing_server> ..\zig\zig.exe run .\server.zig
info: Created server on testing_server.sock
info: Accepted client
error.Unexpected NTSTATUS=0xc000000d (INVALID_PARAMETER)
C:\Users\ab\Desktop\zig\lib\std\Io\Threaded.zig:13017:57: 0x7ff7b3facf89 in netReceiveOneWindows (server_zcu.obj)
        else => |status| return windows.unexpectedStatus(status),
                                                        ^
C:\Users\ab\Desktop\zig\lib\std\Io\Threaded.zig:12961:27: 0x7ff7b3fac3bf in netReceiveWindows (server_zcu.obj)
    t.netReceiveOneWindows(socket_handle, &message_buffer[0], data_buffer, flags) catch |err|
                          ^
C:\Users\ab\Desktop\zig\lib\std\Io\Threaded.zig:2561:55: 0x7ff7b3fad859 in operate (server_zcu.obj)
            if (is_windows) break :o netReceiveWindows(t, o.socket_handle, o.message_buffer, o.data_buffer, o.flags);
                                                      ^
C:\Users\ab\Desktop\zig\lib\std\Io.zig:453:29: 0x7ff7b3ecd216 in operate (server_zcu.obj)
    return io.vtable.operate(io.userdata, operation);
                            ^
C:\Users\ab\Desktop\testing_server\server.zig:27:48: 0x7ff7b3fcd835 in main (server_zcu.obj)
    const err, const len = (try init.io.operate(op)).net_receive;
                                               ^
C:\Users\ab\Desktop\zig\lib\std\start.zig:737: 0x7ff7b3fcdd5f in callMain (server_zcu.obj)
    return wrapMain(root.main(.{

C:\Users\ab\Desktop\zig\lib\std\start.zig:485:17: 0x7ff7b3fcdd5f in WinStartup (server_zcu.obj)
        callMain(std.os.windows.peb().ProcessParameters.CommandLine.slice(), .global),
                ^
???:?:?: 0x7ffab0ff7373 in ??? (KERNEL32.DLL)
???:?:?: 0x7ffab13fcc90 in ??? (ntdll.dll)
error: Unexpected
C:\Users\ab\Desktop\testing_server\server.zig:28:18: 0x7ff7b3fcd9c4 in main (server_zcu.obj)
    if (err) |e| return e;
                 ^

Here’s the minimal server and client example:

// server.zig
pub fn main(init: std.process.Init) !void {
    const unix_path = "testing_server.sock";
    const address = net.UnixAddress.init(unix_path) catch |err| switch (err) {
        error.NameTooLong => unreachable,
    };
    var net_server = address.listen(init.io, .{}) catch |err| {
        std.log.err("Failed to listen to socket {s} {}", .{ unix_path, err });
        return err;
    };
    std.log.info("Created server on {s}", .{address.path});

    const stream = try net_server.accept(init.io);
    std.log.info("Accepted client", .{});

    var buf: [4096]u8 = undefined;
    var msg_buf: [1]net.IncomingMessage = undefined;

    const op: std.Io.Operation = .{
        .net_receive = .{
            .socket_handle = stream.socket.handle,
            .message_buffer = &msg_buf,
            .data_buffer = &buf,
            .flags = .{},
        },
    };

    const err, const len = (try init.io.operate(op)).net_receive;
    if (err) |e| return e;
    std.debug.assert(len == 1);
    std.debug.print("{s}", .{msg_buf[0].data});
}
// client.zig
pub fn main(init: std.process.Init) !void {
    const unix_path = "testing_server.sock";
    const address = net.UnixAddress.init(unix_path) catch |err| switch (err) {
        error.NameTooLong => unreachable,
    };
    const stream = address.connect(init.io) catch |err| {
        std.log.err("Failed to connect to socket {s} {}", .{ unix_path, err });
        return err;
    };
    std.log.info("Connected to server on {s}", .{address.path});

    var buf: [4096]u8 = undefined;
    var writer = stream.writer(init.io, &buf);
    try writer.interface.writeAll("Hello there!\n");
    try writer.interface.flush();

    // prevent disconnecting before the server reads the message
    try init.io.sleep(.fromSeconds(120), .awake);
}

const std = @import("std");
const net = std.Io.net;

Operation.net_receive is only for connectionless protocols (UDP) specifically you can not use this operation to receive on socket not open as connectionless

On linux this works fine. Is this a difference in the windows implementation ? When I look at the std 0.16.0 and master source they both use .stream as the socket mode.

Not sure how to deal with this. I tried using ipv4 and setting mode to .dgram but it returns error.ProtocolUnsupportedByAddressFamily other modes return error.Unexpected.

After using the stream’s reader interface which uses netRead everything works, both linux and windows. Still confused on why net_receive works on linux but not windows.

Thanks for the help!

Very interesting scenario anyway, i will try to do my own investigation soon once i got more of free time