Skip to content
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

VirtualQueryEx 3rd parameter is not an array #284

Closed
AArnott opened this issue Feb 25, 2021 · 3 comments
Closed

VirtualQueryEx 3rd parameter is not an array #284

AArnott opened this issue Feb 25, 2021 · 3 comments
Labels
usability Touch-up to improve the user experience for a language projection

Comments

@AArnott
Copy link
Member

AArnott commented Feb 25, 2021

The VirtualQueryEx method's 3rd parameter is MEMORY_BASIC_INFORMATION* and is not an array. Per the docs, only one struct is expected.

But the metadata attributes it with [NativeArrayInfo(BytesParamIndex = 3)] as if it were an array, leading to CsWin32 projecting it as Span<MEMORY_BASIC_INFORMATION>.

The 4th parameter is supposed to be the length of the struct (just one of them). Capturing this with an attribute (similar to NativeArrayInfo but without the array implication) would allow projections to drop the 4th parameter and auto-fill with the calculated size of the struct, as we're doing now while incorrectly treating it like an array.

@AArnott AArnott added the usability Touch-up to improve the user experience for a language projection label Feb 25, 2021
@AArnott
Copy link
Member Author

AArnott commented Feb 25, 2021

Searching the metadata for other uses of BytesParamIndex I ran across ReadCabinetState which also is incorrectly tagged with an array parameter that is actually a single struct, just like VirtualQueryEx's case.

Same for SHGetFileInfoA and SHGetFileInfoW.

The only valid cases of BytesParamIndex I have found so far is for void* and byte* parameters. Which suggests maybe a pattern the header parser can use to detect whether the pointer parameter really is an array or not.

@sotteson1
Copy link
Contributor

It seems like if I find I need to use BytesParamIndex, I should use a different attribute that just means how big in bytes the pointer points to. That would work for any types, including MEMORY_BASIC_INFORMATION*, void*, and byte*.

@sotteson1
Copy link
Contributor

This will look like:

public unsafe static extern UIntPtr VirtualQueryEx([In] HANDLE hProcess, [Optional][In][Const] void* lpAddress, [Out][MemorySize(BytesParamIndex = 3)] MEMORY_BASIC_INFORMATION* lpBuffer, [In] UIntPtr dwLength);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
usability Touch-up to improve the user experience for a language projection
Projects
None yet
Development

No branches or pull requests

2 participants