microsoft / wdkmetadata

Tooling to generate metadata for Win32 APIs in the Windows Driver Kit (WDK).
Other
96 stars 10 forks source link

feat: Useful names for reparse data buffers #74

Open rbtcollins opened 4 months ago

rbtcollins commented 4 months ago

Right now, I have code like so:

        // Size of the union, -1 for the 1 byte in-struct array, + path lengths.
        let reparse_data_length = mem::size_of::<REPARSE_DATA_BUFFER_0_2>() - 1 + path_length * 2;
        // u32 + USHORT*2
        let reparse_length = reparse_data_length + 8;
        let mut reparse_data_vec: Vec<u8> = vec![0; reparse_length];

sizeof in rust takes types, not paths-to-types. That is, (at least as far as I know), I can't say 'REBASE_DATA_BUFFER::Anonymous::SymbolicLinkReparseBuffer` which of course is what the code above is dealing with.

When I hand-rolled these types I gave them names like so:

        #[repr(C)]
        #[derive(Clone, Copy)]
        pub struct REPARSE_DATA_BUFFER {
            pub ReparseTag: u32,
            pub ReparseDataLength: u16,
            pub Reserved: u16,
            pub u: REPARSE_DATA_BUFFER_u,
        }

        #[repr(C)]
        #[derive(Clone, Copy)]
        pub union REPARSE_DATA_BUFFER_u {
            pub SymbolicLinkReparseBuffer: REPARSE_DATA_BUFFER_u_SymbolicLinkReparseBuffer,
            pub MountPointReparseBuffer: REPARSE_DATA_BUFFER_u_MountPointReparseBuffer,
            pub GenericReparseBuffer: REPARSE_DATA_BUFFER_u_GenericReparseBuffer,
        }

        #[repr(C)]
        #[derive(Clone, Copy)]
        pub struct REPARSE_DATA_BUFFER_u_SymbolicLinkReparseBuffer {
            pub SubstituteNameOffset: u16,
            pub SubstituteNameLength: u16,
            pub PrintNameOffset: u16,
            pub PrintNameLength: u16,
            pub Flags: u32,
            pub PathBuffer: [u16; 1],
        }

        #[repr(C)]
        #[derive(Clone, Copy)]
        pub struct REPARSE_DATA_BUFFER_u_MountPointReparseBuffer {
            pub SubstituteNameOffset: u16,
            pub SubstituteNameLength: u16,
            pub PrintNameOffset: u16,
            pub PrintNameLength: u16,
            pub PathBuffer: [u16; 1],
        }

        #[repr(C)]
        #[derive(Clone, Copy)]
        pub struct REPARSE_DATA_BUFFER_u_GenericReparseBuffer {
            pub DataBuffer: [u16; 1],
        }
ChrisDenton commented 4 months ago

While more descriptive naming on the metadata side would be nice, I think this can also be improved on the rust side.

On stable you can use std::mem::offset_of to get the offset of the path buffer (then add the path length, etc):

let offset = offset_of!(REPARSE_DATA_BUFFER, Anonymous) + offset_of!(REPARSE_DATA_BUFFER_0_1, PathBuffer);

With the nightly feature offset_of_nested this is simplified to:

let offset = offset_of!(REPARSE_DATA_BUFFER, Anonymous.MountPointReparseBuffer.PathBuffer);
rbtcollins commented 4 months ago

Thanks @ChrisDenton ! I'll leave this open as you say, it would be nice to improve, but I'll use your tip myself :).