Skip to content

Variable length arrays in ntdll definitions #6008

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

Open
kubkon opened this issue Aug 10, 2020 · 6 comments
Open

Variable length arrays in ntdll definitions #6008

kubkon opened this issue Aug 10, 2020 · 6 comments
Labels
breaking Implementing this issue could cause existing code to no longer compile or have different behavior. enhancement Solving this issue will likely involve adding new logic or components to the codebase. os-windows standard library This issue involves writing Zig code for the standard library.
Milestone

Comments

@kubkon
Copy link
Member

kubkon commented Aug 10, 2020

@daurnimator suggested leaving out the variable length arrays (VLAs) from some of our NT definitions; for example, we currently have something like this:

pub const FILE_NAME_INFORMATION = extern struct {
    FileNameLength: ULONG,
    FileName: [1]WCHAR,
};

where FileName is effectively a VLA which cannot be known a priori. The idea here is to weed that out leaving only the static elements, so in the above example, leaving in only FileNameLength. FileName VLA can then be accessed by taking a pointer just behind this static structure.

@kubkon kubkon added enhancement Solving this issue will likely involve adding new logic or components to the codebase. breaking Implementing this issue could cause existing code to no longer compile or have different behavior. standard library This issue involves writing Zig code for the standard library. os-windows labels Aug 10, 2020
@kubkon
Copy link
Member Author

kubkon commented Aug 10, 2020

For the record: PR where this discussion originated #5993.

@ikskuh
Copy link
Contributor

ikskuh commented Aug 10, 2020

I think it would be reasonable to include a getter function in structs that use VLAs:

pub const FILE_NAME_INFORMATION = extern struct {
    FileNameLength: ULONG,
    
    pub fn getFileName(self: *@This()) []WCHAR {
        return @intToPtr([*]WCHAR, @ptrToInt(self) + @sizeOf(ULONG))[0..self.FileNameLength];
    }
};

@kubkon
Copy link
Member Author

kubkon commented Aug 10, 2020

I think it would be reasonable to include a getter function in structs that use VLAs:

pub const FILE_NAME_INFORMATION = extern struct {
    FileNameLength: ULONG,
    
    pub fn getFileName(self: *@This()) []WCHAR {
        return @intToPtr([*]WCHAR, @ptrToInt(self) + @sizeOf(ULONG))[0..self.FileNameLength];
    }
};

That's a cool idea, I like it!

@daurnimator
Copy link
Contributor

I think it would be reasonable to include a getter function in structs that use VLAs:

Note that I've hit zig bugs doing this in the past.

might be fixed now though

@kubkon
Copy link
Member Author

kubkon commented Aug 11, 2020

I think it would be reasonable to include a getter function in structs that use VLAs:

Note that I've hit zig bugs doing this in the past.

might be fixed now though

Thanks for the heads up @daurnimator!

@Pyrolistical
Copy link
Contributor

Pyrolistical commented May 10, 2024

I wrote a generic version:

pub fn getFileName(comptime T: type, t: *T) []std.os.windows.WCHAR {
    comptime var file_name_offset = 0;
    switch (@typeInfo(T)) {
        .Struct => |struct_info| {
            if (struct_info.layout != .@"extern") {
                @compileError("expected extern struct but was " ++ @tagName(struct_info.layout));
            }
            inline for (struct_info.fields) |field| {
                if (std.mem.eql(u8, field.name, "FileName")) {
                    break;
                }
                file_name_offset += @sizeOf(field.type);
            }
        },
        else => @compileError("expected T to be a struct but was " ++ @typeName(T)),
    }
    const file_name_ptr: [*]std.os.windows.WCHAR = @ptrFromInt(@intFromPtr(t) + file_name_offset);
    const file_name_length_in_bytes = @field(t, "FileNameLength");
    const file_name_length_in_wchars = file_name_length_in_bytes / @sizeOf(std.os.windows.WCHAR);
    return file_name_ptr[0..file_name_length_in_wchars];
}

Works for structs that declare or remove the FileName: [1]WCHAR field.

@MasterQ32 I believe your original code had a bug in it. FileNameLength in the unit of bytes and not the length of the WCHAR FileName

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking Implementing this issue could cause existing code to no longer compile or have different behavior. enhancement Solving this issue will likely involve adding new logic or components to the codebase. os-windows standard library This issue involves writing Zig code for the standard library.
Projects
None yet
Development

No branches or pull requests

6 participants