-
Notifications
You must be signed in to change notification settings - Fork 114
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
LoadLibraryEx missing critical [Optional]
attribute on reserved parameter
#1421
Comments
For what it's worth, the Rust projection just treats |
Is it safe to assume that all reserved fields/parameters are documented as requiring |
To @kennykerr's point, maybe the metadata should always add |
Yep, reserved parameters are always zero. And yes, I'd prefer a single way to describe these rather than having to check for both optional and reserved. |
Doesn't look like there's a bug here. Instead, the C# projection was not looking at the |
Agreed. The metadata matches the headers and C#/Win32 should add support for |
Maybe we should start documenting these things then. The fact that |
Just a note: |
What do you mean by that? Optional is an attribute: https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.optionalattribute?view=net-7.0. |
That's just a synthesized attribute that .NET uses to represent the |
@mikebattista it appears in source code and in decompiled source, but ya, it's not really there in the compiled form, as @kennykerr says. The attribute is just there to help C# source code to indicate to the compiler that they want the flag set. I have hit a snag though. It seems the metadata includes the One example is the IEnumNetCfgComponent::Clone method. It is documented as "do not use", so maybe the reserved flag on the parameter is better applied to the whole method? Another example is IEnumScript::Clone which is not documented as "do not use". Both of these methods are interesting because they have exactly one simple function, which is entirely dependent on the caller consuming the result of its out parameter, so having that out parameter be marked reserved seems bonkers. |
The metadata is following the |
Understood. IMO though, as this repo is responsible for translating headers to a ECMA representation, it should reliably set the optional flag based on whether parameters accept null values. If getting this from the headers requires considering both the reserved and optional SAL annotations, that seems like it should be the job of this repo instead of the projections. |
If we added [Optional] in addition to [Reserved] would that work? Are [Reserved] parameters always semantically equivalent to [Optional]? Or does [Reserved] in the metadata never have any value other than [Optional], and we should remove it entirely? |
The two are not equivalent. We should not remove 1 Out parameters with |
Aside from your footnote, are you saying projections should just drop parameters marked with Reserved? If so, what's the value of adding Optional? If that's not correct or not all projections would do that, do you agree that adding [Optional] in addition to [Reserved] is the right thing? |
Dropping reserved parameters would be a decision to be made by the projection. They can't really drop them, since it's part of the binary interface, but in CsWin32's case we can drop them from the friendly overloads. At that point, CsWin32 no longer cares about the Optional attribute being present as well. But for any projection that doesn't want to or can't produce overloads, some (e.g. Rust) would still want to know when a value is allowed to be null.
Yes, primarily because Reserved is an attribute that IMO ought to be safe for a projection to ignore. |
@kennykerr are you ok with this? Adding [Optional] to all [Reserved] parameters? |
We should consider that reserved parameters are reserved by Microsoft for future use. This future may change the optional nature of the parameter for some future scenario, which may require projections to emit this parameter. |
Cloning the script enumerator does not appear to be implemented, which makes the reserved attribute make sense. use windows::Win32::{
Globalization::{
CMultiLanguage, IMultiLanguage3, SCRIPTCONTF_SCRIPT_SYSTEM, SCRIPTCONTF_SCRIPT_USER,
},
System::Com::{
CoCreateInstance, CoInitializeEx, CLSCTX_INPROC_SERVER, COINIT_MULTITHREADED,
},
};
fn main() -> windows::core::Result<()> {
unsafe {
CoInitializeEx(None, COINIT_MULTITHREADED)?;
let language: IMultiLanguage3 =
CoCreateInstance(&CMultiLanguage, None, CLSCTX_INPROC_SERVER)?;
let scripts = language.EnumScripts(
SCRIPTCONTF_SCRIPT_USER.0 as u32 | SCRIPTCONTF_SCRIPT_SYSTEM.0 as u32,
1033,
)?;
dbg!(scripts.Clone());
}
Ok(())
} produces
|
Sure that's fine but if you're not going to drop reserved, I don't really see the point. I agree with @riverar that reserved parameters are just optional parameters that currently have no other supported values, other than zero, but may in future. Anyway, if you're going to slap optional on all reserved parameters let's just make sure it's done reliably so that tools that don't distinguish between them don't have to check for both. |
I believe @AArnott wants to hide reserved parameters from the developer and only provide overloaded methods w/ optional parameters (if any). He can't do that if we semantically merge the I think for projections that can't use or don't need this distinction, |
The docs for
LoadLibraryEx
dictate that thehFile
parameter is reserved and must be NULL. But the metadata does not attribute the parameter with[Optional]
, so the C# projection throws when null is passed in.Contrast this with
CreateFile
, which does attribute itshTemplateFile
parameter as[Optional]
:This was caught by @Arebusf21 as reported in microsoft/CsWin32#839.
The text was updated successfully, but these errors were encountered: