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

Regression: Flags are not being marked as unsigned #1502

Closed
timsneath opened this issue Mar 18, 2023 · 41 comments · Fixed by #1572
Closed

Regression: Flags are not being marked as unsigned #1502

timsneath opened this issue Mar 18, 2023 · 41 comments · Fixed by #1572
Assignees

Comments

@timsneath
Copy link
Contributor

Per generationOptions.md, --enumMakeFlags tells the emitter to add the [Flags] attribute and also to make the enum unsigned.

In generation\WinSDK\emitter.settings.rsp, COINIT is listed under the --enumMakeFlags section, but is now converted to int32 in the metadata:

.class public auto ansi sealed Windows.Win32.System.Com.COINIT
	extends [netstandard]System.Enum
{
	.custom instance void [netstandard]System.FlagsAttribute::.ctor() = (
		01 00 00 00
	)
	// Fields
	.field public specialname rtspecialname int32 value__
	.field public static literal valuetype [Windows.Win32.winmd]Windows.Win32.System.Com.COINIT COINIT_APARTMENTTHREADED = int32(2)
	.field public static literal valuetype [Windows.Win32.winmd]Windows.Win32.System.Com.COINIT COINIT_MULTITHREADED = int32(0)
	.field public static literal valuetype [Windows.Win32.winmd]Windows.Win32.System.Com.COINIT COINIT_DISABLE_OLE1DDE = int32(4)
	.field public static literal valuetype [Windows.Win32.winmd]Windows.Win32.System.Com.COINIT COINIT_SPEED_OVER_MEMORY = int32(8)

} // end of class Windows.Win32.System.Com.COINIT

Others are also incorrectly shown as signed, for example Windows.Win32.Storage.Vhd.COMPACT_VIRTUAL_DISK_FLAG.

@riverar
Copy link
Collaborator

riverar commented Mar 18, 2023

Any other information (e.g. what version this was working in)?

@mikebattista
Copy link
Contributor

The fact that all flags enums were being forced to uint was a bug. We fixed that with #1478. Enum types now match their native types as scraped by ClangSharp.

Are you just pointing out a documentation discrepancy here? Or are you not able to use the APIs?

@riverar
Copy link
Collaborator

riverar commented Mar 18, 2023

Or maybe just be a few releases behind? 🙃

mikebattista added a commit that referenced this issue Mar 20, 2023
@mikebattista
Copy link
Contributor

Closing as by design. I updated the docs. Reactivate if you run into usability issues.

@mikebattista mikebattista closed this as not planned Won't fix, can't repro, duplicate, stale Mar 20, 2023
@timsneath
Copy link
Contributor Author

COINIT should definitely not be signed. It's a DWORD (which is of course defined as unsigned long):
https://learn.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-coinitializeex

@timsneath
Copy link
Contributor Author

@mikebattista Looks like I don't have permissions to reopen an issue after you've closed it.

@mikebattista mikebattista reopened this Mar 20, 2023
@mikebattista
Copy link
Contributor

@tannergooding I thought we should trust ClangSharp's types here per #1369 (comment).

Is ClangSharp getting this wrong?

@tannergooding
Copy link
Member

tannergooding commented Mar 20, 2023

@timsneath, @mikebattista

The CoInitializeEx API does not take COINIT, it takes a DWORD and relies on C/C++ implicit casts to be passed in without conversion.

The actual COINIT enum is in fact signed and this can be trivially seen in MSVC codegen such as on godbolt

@mikebattista
Copy link
Contributor

@timsneath are you able to pass COINIT flags to CoInitializeEx without needing to cast?

@tannergooding
Copy link
Member

C#/.NET won't let you for sure nor will some other languages, such as Rust. They are both strongly typed and won't let you implicit convert from something that has a more constrained domain (such as an enum) to something with a broader or different domain (such as int or uint since that changes sign).

There are in fact CPU architectures, such as RISC-V, where the sign of types is important. On a 64-bit RISC-V system, a signed value is passed differently from an unsigned value. So preserving this information correct/accurately is a core requirement, particularly if Windows supports such architectures in the future.

@mikebattista
Copy link
Contributor

Below is our metadata definition. Will that be usable as expected without casting?

[DllImport("OLE32.dll", ExactSpelling = true, PreserveSig = false)]
[SupportedOSPlatform("windows5.0")]
public unsafe static extern HRESULT CoInitializeEx([Optional][In] void* pvReserved, [In] COINIT dwCoInit);

[Flags]
public enum COINIT
{
	COINIT_APARTMENTTHREADED = 2,
	COINIT_MULTITHREADED = 0,
	COINIT_DISABLE_OLE1DDE = 4,
	COINIT_SPEED_OVER_MEMORY = 8
}

@tannergooding
Copy link
Member

Will that be usable as expected without casting?

Yes. But the definition of CoInitializeEx is "not correct" and may cause problems on future platforms, such as RISC-V.

We really shouldn't be changing signatures anywhere, even for convenience. We should directly map to the C/C++ ABI and should only provide convenience in the form of additional metadata -- e.g. We should have uint dwCoInit and if it is worthwhile to provide additional metadata such as [NativeTypeName("DWORD")] or some hypothetical [AssociatedEnum(typeof(COINIT))].

@tannergooding
Copy link
Member

That means that by default users will have to do CoInitializeEx(null, (uint)(COINIT.COINIT_APARTMENTTHREADED | ...))

However, it will guarantee correctness and tooling, such as CsWin32, can provide a convenience wrapper which handles the casting for them while still preserving ABI correctness.

@riverar
Copy link
Collaborator

riverar commented Mar 20, 2023

Feels like we're off track. The problem, as I see it, is the COINIT enum is defaulting to values of int. I believe the only change needed here is that enum (e.g. enum COINIT : uint).

@tannergooding
Copy link
Member

I believe the only change needed here is that enum (e.g. enum COINIT : uint).

This is an incorrect change as I've already iterated above. COINIT in C/C++ is signed and it is important it stay signed.

@riverar
Copy link
Collaborator

riverar commented Mar 20, 2023

Are you saying the implementation expects a signed integer and that the headers are wrong?

@tannergooding
Copy link
Member

Are you saying the implementation expects a signed integer and that the headers are wrong?

No. There is an API defined in um/combaseapi.h:

_Check_return_
WINOLEAPI
CoInitializeEx(
    _In_opt_ LPVOID pvReserved,
    _In_ DWORD dwCoInit
    );

There is then an enum defined in um/objbase.h:

typedef enum tagCOINIT
{
  COINIT_APARTMENTTHREADED  = 0x2,      // Apartment model

#if  (_WIN32_WINNT >= 0x0400 ) || defined(_WIN32_DCOM) // DCOM
  // These constants are only valid on Windows NT 4.0
  COINIT_MULTITHREADED      = COINITBASE_MULTITHREADED,
  COINIT_DISABLE_OLE1DDE    = 0x4,      // Don't use DDE for Ole1 support.
  COINIT_SPEED_OVER_MEMORY  = 0x8,      // Trade memory for speed.
#endif // DCOM
} COINIT;

There is no API CoInitializeEx that takes COINIT directly. The signs of COINIT and DWORD are different and it is important to preserve that information/fact. C/C++, being C/C++ and having many types of implicit casts allow this to "just work". Other languages do not have such conversion and this may require more explicit code on such targets.

@mikebattista
Copy link
Contributor

So your feedback is in cases where the types differ, we should not encode the friendly enum in the parameter type in the metadata. Users of the API will need to cast. Is that right?

@riverar
Copy link
Collaborator

riverar commented Mar 20, 2023

I suspect the COINIT definition (with signed integers) is more of a human error or legacy artifact resulting from old ISO C standards/compilers. The author clearly intended to pass in flags. And there's no ABI difference on x86, x64, or arm64.

It may be a good point for RISC-V but by the time we have to worry about that, metadata may look very different.

@tannergooding
Copy link
Member

we should not encode the friendly enum in the parameter type in the metadata. Users of the API will need to cast. Is that right?

Yes. That would be required for ABI correctness.

I do think providing additional metadata, in the form of attributes, so that tooling can help provide safe wrapper APIs is fine.

For example, providing some [AssociatedEnum(typeof(COINIT))] uint dwCoInit allows the API to be correct from the ABI perspective while simultaneously allowing tooling, such as CsWin32, to understand the relationship with the COINIT enum and that it can surface that relationship as appropriate in the C# bindings it generates. It could, for example, generate:

public static HRESULT CoInitializeEx(void* pvReserved, COINIT dwCoInit)
{
    return (HRESULT)CoInitializeEx(pvReserved, (uint)dwCoInit);
}

[DllImport("ole32", ExactSpelling = true)]
private static extern int CoInitializeEx(void* pvReserved, uint dwCoInit);

@tannergooding
Copy link
Member

And there's no ABI difference on x86, x64, or arm64. https://godbolt.org/z/sxKffa15c

Intent does not matter here. The reality is, for better or worse, that these differ.

win32metadata is meant to provide correct metadata such that other tools/languages can generate idiomatic projections. It will have failed at that if it starts providing opinions or exposing metadata in a way that is strictly not ABI compatible.

There is also a lot more than just ABI consideration to take into account. There is also the impact of other code that may be ported or involved, including code outside the realm of the win32metadata repo.

Simply comparing a COINIT against zero has changed meaning between it being signed vs unsigned and while I'm not aware of any code that is doing that with COINIT in particular, there are APIs that do that with other enums many of which likewise have a signed enum vs API takes DWORD split.

As does upcasting it to int64_t/uint64_t, reading/writing it in a compressed bitfield, performing right shift operations, and many other scenarios.

@tannergooding
Copy link
Member

The repo can and likely should still provide all the necessary information such that tooling can generate friendly bindings still.

It just requires representing that information via additional metadata to ensure correctness by default and niceness by extension if the tooling decides it wants to utilize what information is available.

@mikebattista
Copy link
Contributor

Thanks for the insight Tanner.

We have a test that warns for enum remaps that change the size of the parameter/field (from uint to ushort, for example), but it doesn't yet warn against sign changes like this.

I'm going to explore updating that test to detect sign changes to see how widespread the issue is now that we honor the native types of the enums. Then we can decide how to handle.

@timsneath
Copy link
Contributor Author

timsneath commented Mar 20, 2023

The main issue that I have right now is that CoInitializeEx is suddenly redefined as taking a int32 type, rather than a uint32 type. This is a breaking change for Dart, where the FFI library sees these as fundamentally different types.

Like @riverar, I see it as merely an idiosyncrasy that COINIT is marked as a signed int, since it's only ever passed to Windows as a DWORD. There is no valid scenario where a negative value here is correct. (There are other enums that probably fall into this category, but this one is so broadly applicable that the change is very disruptive.)

If I understand the header file correctly, the enum is not defined as either a signed or an unsigned integer: C does not distinguish itself between the two, and therefore the API should be normative in terms of establishing this? Or am I misunderstanding things? I'm trying to understand why you believe "COINIT in C/C++ is signed and it is important it stay signed", @tannergooding...

@riverar
Copy link
Collaborator

riverar commented Mar 20, 2023

Tanner has a fair point regarding the ABI issue when you start to think about win32metadata/non-win32metadata code co-mingling).

@timsneath I believe the proposal on the table is to:

  • correct CoInitializeEx definition to accept unsigned integers
  • correct COINIT definition to be an enumeration of signed integers
  • investigate adding additional metadata on that parameter so that projection authors can emit code to improve developer experience

@mikebattista
Copy link
Contributor

mikebattista commented Mar 20, 2023

Yes that is the proposal. COINIT as of the latest build is already signed so really the ask is 1 and 3.

The other ask is to update our enum remapping test to identify sign changes like this.

@tannergooding
Copy link
Member

tannergooding commented Mar 20, 2023

There is no valid scenario where a negative value here is correct

There is far more to be considerate of than simply what APIs the headers expose as there are millions of lines of user code that use such types and which do get ported or converted to other languages.

A simple example of where a negative value may be encountered is one such as using it as a sentinel to represent an operation that hasn't been completed yet:

public class C
{
    private COINIT _coinitState = (COINIT)(-1);

    public void DoSomething()
    {
        if (_coinitState < 0)
        {
            COINIT coinitState = ...;
            CoInitializeEx(null, (uint)coinitState);
            _coinitState = coinitState;
        }

        // rest of the logic
    }
}

Changing the sign of the enum changes the meaning of this code and therefore what happens. This is a case where it would probably get caught relatively quickly, but it is a deviation from how equivalent code functioned in C/C++.

If I understand the header file correctly, the enum is not defined as either a signed or an unsigned integer: C does not distinguish itself between the two, and therefore the API should be normative in terms of establishing this? Or am I misunderstanding things? I'm trying to understand why you believe "COINIT in C/C++ is signed and it is important it stay signed"

@timsneath

C++ explicitly defines it to be int if not otherwise specified.

You're correct that C does not explicitly distinguish between them. It is partially implementation defined as to the size and sign of an arbitrary enum just that it shall be one of char, a signed integer type, or an unsigned integer type and that it shall be capable of representing all the values of all the members of the enumeration.

However, Windows has always treated them as int and so MSVC, Clang, and GCC compile them as int on Windows. This is even the case if you define one as 0x80000000U or -9223372036854775808LL. -- Just one of the "fun" quirks of the languages/targets

I believe the proposal on the table is to:

That matches my expectations.

In the case of Dart, it should then be able to continue seeing that CoInitializeEx takes uint and it can optionally utilize the "additional metadata" to provide a helper wrapper that takes COINIT and does the necessary casting before the call into ole32.

@timsneath
Copy link
Contributor Author

"C++ explicitly defines it to be int if not otherwise specified." -- ah, thank you! That's the subtlety I was missing out on. Your motivating example is good too (even though it seems like a poor choice to set an enum to a deliberately invalid value, I'm sure I've written worse code myself in the past!)

But yeah, so long as we take care of 1 on the above list, I'll be a very happy camper! I can't currently roll out the latest metadata file because I'd break too many users, so fixing this would be much appreciated.

@tannergooding
Copy link
Member

even though it seems like a poor choice to set an enum to a deliberately invalid value, I'm sure I've written worse code myself in the past!

Was mostly giving a representative example of what someone might do. Notably some languages, like rust, may allow this as part of niche filling for Option<T>. You might represent it as Option<NonZeroI32> for example, that way you don't have to track "2 fields" and can explicitly use an "invalid value" as a perf/space optimization. It's much akin to using null for the same thing with reference/pointer types.

@mikebattista
Copy link
Contributor

mikebattista commented Mar 21, 2023

Below are the sign mismatch issues after fixing what could be fixed.

These should mostly be scraped enums of one type that are assigned to a parameter or field of another type. Manual enums defined in enums.json that have issues are usually the result of being assigned to a mismatch of types.

All these assignments should be removed and a new attribute should be added instead to allow projections to improve the developer experience if they can.

I'll remove the assignments to close this issue and will create a separate issue to track a new attribute.

CERT_RDN_ATTR in Security.Cryptography.modified.cs: CERT_RDN_ATTR.dwValueType was remapped to enum Windows.Win32.Security.Cryptography.CERT_RDN_ATTR_VALUE_TYPE (type int, size 4) but the original field was of type DWORD (size 4).
CHANGENOTIFY in Controls.RichEdit.modified.cs: CHANGENOTIFY.dwChangeType was remapped to enum Windows.Win32.UI.Controls.RichEdit.CHANGETYPE (type int, size 4) but the original field was of type DWORD (size 4).
CoInitializeEx.dwCoInit was remapped to enum Windows.Win32.System.Com.COINIT (type int, size 4) but the original field was of type DWORD (size 4).
CONTROLINFO in ComOle.modified.cs: CONTROLINFO.dwFlags was remapped to enum Windows.Win32.System.Ole.CTRLINFO (type int, size 4) but the original field was of type DWORD (size 4).
D3D11_BUFFER_DESC in Direct3D11.modified.cs: D3D11_BUFFER_DESC.BindFlags was remapped to enum Windows.Win32.Graphics.Direct3D11.D3D11_BIND_FLAG (type int, size 4) but the original field was of type UINT (size 4).
D3D11_TEXTURE1D_DESC in Direct3D11.modified.cs: D3D11_TEXTURE1D_DESC.BindFlags was remapped to enum Windows.Win32.Graphics.Direct3D11.D3D11_BIND_FLAG (type int, size 4) but the original field was of type UINT (size 4).
D3D11_TEXTURE2D_DESC in Direct3D11.modified.cs: D3D11_TEXTURE2D_DESC.BindFlags was remapped to enum Windows.Win32.Graphics.Direct3D11.D3D11_BIND_FLAG (type int, size 4) but the original field was of type UINT (size 4).
D3D11_TEXTURE2D_DESC1 in Direct3D11.modified.cs: D3D11_TEXTURE2D_DESC1.BindFlags was remapped to enum Windows.Win32.Graphics.Direct3D11.D3D11_BIND_FLAG (type int, size 4) but the original field was of type UINT (size 4).
D3D11_TEXTURE3D_DESC in Direct3D11.modified.cs: D3D11_TEXTURE3D_DESC.BindFlags was remapped to enum Windows.Win32.Graphics.Direct3D11.D3D11_BIND_FLAG (type int, size 4) but the original field was of type UINT (size 4).
D3D11_TEXTURE3D_DESC1 in Direct3D11.modified.cs: D3D11_TEXTURE3D_DESC1.BindFlags was remapped to enum Windows.Win32.Graphics.Direct3D11.D3D11_BIND_FLAG (type int, size 4) but the original field was of type UINT (size 4).
DOCHOSTUIINFO in MsHtml.modified.cs: DOCHOSTUIINFO.dwFlags was remapped to enum Windows.Win32.Web.MsHtml.DOCHOSTUIFLAG (type int, size 4) but the original field was of type DWORD (size 4).
DwmGetWindowAttribute.dwAttribute was remapped to enum Windows.Win32.Graphics.Dwm.DWMWINDOWATTRIBUTE (type int, size 4) but the original field was of type DWORD (size 4).
DXVA2_DecodeBufferDesc in Mf.modified.cs: DXVA2_DecodeBufferDesc.CompressedBufferType was remapped to enum Windows.Win32.Media.MediaFoundation.DXVA2_BufferfType (type int, size 4) but the original field was of type DWORD (size 4).
EMREXTSELECTCLIPRGN in Gdi.modified.cs: EMREXTSELECTCLIPRGN.iMode was remapped to enum Windows.Win32.Graphics.Gdi.RGN_COMBINE_MODE (type int, size 4) but the original field was of type DWORD (size 4).
EXTLOGPEN in Gdi.modified.cs: EXTLOGPEN.elpPenStyle was remapped to enum Windows.Win32.Graphics.Gdi.PEN_STYLE (type int, size 4) but the original field was of type DWORD (size 4).
EXTLOGPEN32 in Gdi.modified.cs: EXTLOGPEN32.elpPenStyle was remapped to enum Windows.Win32.Graphics.Gdi.PEN_STYLE (type int, size 4) but the original field was of type DWORD (size 4).
FlatSB_SetScrollProp.index was remapped to enum Windows.Win32.UI.Controls.WSB_PROP (type int, size 4) but the original field was of type UINT (size 4).
GetCurrentPackageId.return was remapped to enum Windows.Win32.Foundation.WIN32_ERROR (type uint, size 4) but the original field was of type LONG (size 4).
GetDisplayConfigBufferSizes.return was remapped to enum Windows.Win32.Foundation.WIN32_ERROR (type uint, size 4) but the original field was of type LONG (size 4).
HtmlHelpA.uCommand was remapped to enum Windows.Win32.Data.HtmlHelp.HTML_HELP_COMMAND (type int, size 4) but the original field was of type UINT (size 4).
IAMMultiMediaStream in Media.DShow.modified.cs: IAMMultiMediaStream.Initialize.dwFlags was remapped to enum Windows.Win32.Media.DirectShow.AMMSF_MMS_INIT_FLAGS (type int, size 4) but the original field was of type DWORD (size 4).
IAzClientContext3 in Authorization.modified.cs: IAzClientContext3.GetGroups.ulOptions was remapped to enum Windows.Win32.Security.Authorization.AZ_PROP_CONSTANTS (type int, size 4) but the original field was of type ULONG (size 4).
IClientSecurity in Com.modified.cs: IClientSecurity.SetBlanket.dwCapabilities was remapped to enum Windows.Win32.System.Com.EOLE_AUTHENTICATION_CAPABILITIES (type int, size 4) but the original field was of type DWORD (size 4).
IDirectXVideoAccelerationService in Mf.modified.cs: IDirectXVideoAccelerationService.CreateSurface.DxvaType was remapped to enum Windows.Win32.Media.MediaFoundation.DXVA2_VideoRenderTargetType (type int, size 4) but the original field was of type DWORD (size 4).
IDirectXVideoDecoder in Mf.modified.cs: IDirectXVideoDecoder.GetBuffer.BufferType was remapped to enum Windows.Win32.Media.MediaFoundation.DXVA2_BufferfType (type int, size 4) but the original field was of type UINT (size 4).
IFolderView in Shell.modified.cs: IFolderView.ItemCount.uFlags was remapped to enum Windows.Win32.UI.Shell._SVGIO (type int, size 4) but the original field was of type UINT (size 4).
IIdentityAdvise in IdentityProvider.modified.cs: IIdentityAdvise.IdentityUpdated.dwIdentityUpdateEvents was remapped to enum Windows.Win32.Security.Authentication.Identity.Provider.IdentityUpdateEvent (type int, size 4) but the original field was of type DWORD (size 4).
IIdentityProvider in IdentityProvider.modified.cs: IIdentityProvider.Advise.dwIdentityUpdateEvents was remapped to enum Windows.Win32.Security.Authentication.Identity.Provider.IdentityUpdateEvent (type int, size 4) but the original field was of type DWORD (size 4).
IImePad in Input.Ime.modified.cs: IImePad.Request.reqId was remapped to enum Windows.Win32.UI.Input.Ime.IME_PAD_REQUEST_FLAGS (type uint, size 4) but the original field was of type INT (size 4).
ILockBytes in Com.modified.cs: ILockBytes.LockRegion.dwLockType was remapped to enum Windows.Win32.System.Com.LOCKTYPE (type int, size 4) but the original field was of type DWORD (size 4).
IOleClientSite in ComOle.modified.cs: IOleClientSite.GetMoniker.dwAssign was remapped to enum Windows.Win32.System.Ole.OLEGETMONIKER (type int, size 4) but the original field was of type DWORD (size 4).
IOleContainer in ComOle.modified.cs: IOleContainer.EnumObjects.grfFlags was remapped to enum Windows.Win32.System.Ole.OLECONTF (type int, size 4) but the original field was of type DWORD (size 4).
IOleControlSite in ComOle.modified.cs: IOleControlSite.TransformCoords.dwFlags was remapped to enum Windows.Win32.System.Ole.XFORMCOORDS (type int, size 4) but the original field was of type DWORD (size 4).
IOleObject in ComOle.modified.cs: IOleObject.Close.dwSaveOption was remapped to enum Windows.Win32.System.Ole.OLECLOSE (type int, size 4) but the original field was of type DWORD (size 4).
IPropertyPage in ComOle.modified.cs: IPropertyPage.Show.nCmdShow was remapped to enum Windows.Win32.UI.WindowsAndMessaging.SHOW_WINDOW_CMD (type int, size 4) but the original field was of type UINT (size 4).
IPropertyPageSite in ComOle.modified.cs: IPropertyPageSite.OnStatusChange.dwFlags was remapped to enum Windows.Win32.System.Ole.PROPPAGESTATUS (type int, size 4) but the original field was of type DWORD (size 4).
IQueryInfo in Shell.modified.cs: IQueryInfo.GetInfoTip.dwFlags was remapped to enum Windows.Win32.UI.Shell.QITIPF_FLAGS (type int, size 4) but the original field was of type DWORD (size 4).
IRecordInfo in ComOle.modified.cs: IRecordInfo.PutField.wFlags was remapped to enum Windows.Win32.System.Com.INVOKEKIND (type int, size 4) but the original field was of type ULONG (size 4).
IShellFolderView in Shell.modified.cs: IShellFolderView.Select.dwFlags was remapped to enum Windows.Win32.UI.Shell.SFVS_SELECT (type int, size 4) but the original field was of type UINT (size 4).
IShellFolderViewCB in Shell.modified.cs: IShellFolderViewCB.MessageSFVCB.uMsg was remapped to enum Windows.Win32.UI.Shell.SFVM_MESSAGE_ID (type int, size 4) but the original field was of type UINT (size 4).
IShellView in Shell.modified.cs: IShellView.GetItemObject.uItem was remapped to enum Windows.Win32.UI.Shell._SVGIO (type int, size 4) but the original field was of type UINT (size 4).
IStorage in Com.modified.cs: IStorage.MoveElementTo.grfFlags was remapped to enum Windows.Win32.System.Com.StructuredStorage.STGMOVE (type int, size 4) but the original field was of type DWORD (size 4).
IStream in Com.modified.cs: IStream.Commit.grfCommitFlags was remapped to enum Windows.Win32.System.Com.STGC (type int, size 4) but the original field was of type DWORD (size 4).
IVBGetControl in ComOle.modified.cs: IVBGetControl.EnumControls.dwOleContF was remapped to enum Windows.Win32.System.Ole.OLECONTF (type int, size 4) but the original field was of type DWORD (size 4).
IViewObject in ComOle.modified.cs: IViewObject.SetAdvise.advf was remapped to enum Windows.Win32.System.Com.ADVF (type int, size 4) but the original field was of type DWORD (size 4).
IWPCProviderConfig in Parcon.modified.cs: IWPCProviderConfig.RequestOverride.dwFlags was remapped to enum Windows.Win32.System.ParentalControls.WPCFLAG_RESTRICTION (type int, size 4) but the original field was of type DWORD (size 4).
IWSCProductList in SecurityCenter.modified.cs: IWSCProductList.Initialize.provider was remapped to enum Windows.Win32.System.SecurityCenter.WSC_SECURITY_PROVIDER (type int, size 4) but the original field was of type ULONG (size 4).
JOBOBJECT_IO_RATE_CONTROL_INFORMATION in JobObjects.modified.cs: JOBOBJECT_IO_RATE_CONTROL_INFORMATION.ControlFlags was remapped to enum Windows.Win32.System.JobObjects.JOB_OBJECT_IO_RATE_CONTROL_FLAGS (type int, size 4) but the original field was of type ULONG (size 4).
LdapMapErrorToWin32.LdapError was remapped to enum Windows.Win32.Networking.Ldap.LDAP_RETCODE (type int, size 4) but the original field was of type ULONG (size 4).
LOGPEN in Gdi.modified.cs: LOGPEN.lopnStyle was remapped to enum Windows.Win32.Graphics.Gdi.PEN_STYLE (type int, size 4) but the original field was of type UINT (size 4).
MFTEnumEx.Flags was remapped to enum Windows.Win32.Media.MediaFoundation.MFT_ENUM_FLAG (type int, size 4) but the original field was of type UINT32 (size 4).
MsiEnableLogA.dwLogMode was remapped to enum Windows.Win32.System.ApplicationInstallationAndServicing.INSTALLLOGMODE (type int, size 4) but the original field was of type DWORD (size 4).
NTMS_DRIVEINFORMATIONA in Fs.modified.cs: NTMS_DRIVEINFORMATIONA.State was remapped to enum Windows.Win32.Storage.FileSystem.NtmsDriveState (type int, size 4) but the original field was of type DWORD (size 4).
NTMS_DRIVEINFORMATIONW in Fs.modified.cs: NTMS_DRIVEINFORMATIONW.State was remapped to enum Windows.Win32.Storage.FileSystem.NtmsDriveState (type int, size 4) but the original field was of type DWORD (size 4).
NTMS_IEDOORINFORMATION in Fs.modified.cs: NTMS_IEDOORINFORMATION.State was remapped to enum Windows.Win32.Storage.FileSystem.NtmsDoorState (type int, size 4) but the original field was of type DWORD (size 4).
NTMS_IEPORTINFORMATION in Fs.modified.cs: NTMS_IEPORTINFORMATION.Content was remapped to enum Windows.Win32.Storage.FileSystem.NtmsPortContent (type int, size 4) but the original field was of type DWORD (size 4).
NTMS_LIBRARYINFORMATION in Fs.modified.cs: NTMS_LIBRARYINFORMATION.LibraryType was remapped to enum Windows.Win32.Storage.FileSystem.NtmsLibraryType (type int, size 4) but the original field was of type DWORD (size 4).
NTMS_LIBREQUESTINFORMATIONA in Fs.modified.cs: NTMS_LIBREQUESTINFORMATIONA.OperationCode was remapped to enum Windows.Win32.Storage.FileSystem.NtmsLmOperation (type int, size 4) but the original field was of type DWORD (size 4).
NTMS_LIBREQUESTINFORMATIONW in Fs.modified.cs: NTMS_LIBREQUESTINFORMATIONW.OperationCode was remapped to enum Windows.Win32.Storage.FileSystem.NtmsLmOperation (type int, size 4) but the original field was of type DWORD (size 4).
NTMS_MEDIATYPEINFORMATION in Fs.modified.cs: NTMS_MEDIATYPEINFORMATION.ReadWriteCharacteristics was remapped to enum Windows.Win32.Storage.FileSystem.NtmsReadWriteCharacteristics (type int, size 4) but the original field was of type DWORD (size 4).
NTMS_NOTIFICATIONINFORMATION in Fs.modified.cs: NTMS_NOTIFICATIONINFORMATION.dwOperation was remapped to enum Windows.Win32.Storage.FileSystem.NtmsNotificationOperations (type int, size 4) but the original field was of type DWORD (size 4).
NTMS_OBJECTINFORMATIONA in Fs.modified.cs: NTMS_OBJECTINFORMATIONA.dwType was remapped to enum Windows.Win32.Storage.FileSystem.NtmsObjectsTypes (type int, size 4) but the original field was of type DWORD (size 4).
NTMS_OBJECTINFORMATIONW in Fs.modified.cs: NTMS_OBJECTINFORMATIONW.dwType was remapped to enum Windows.Win32.Storage.FileSystem.NtmsObjectsTypes (type int, size 4) but the original field was of type DWORD (size 4).
NTMS_OPREQUESTINFORMATIONA in Fs.modified.cs: NTMS_OPREQUESTINFORMATIONA.Request was remapped to enum Windows.Win32.Storage.FileSystem.NtmsOpreqCommand (type int, size 4) but the original field was of type DWORD (size 4).
NTMS_OPREQUESTINFORMATIONW in Fs.modified.cs: NTMS_OPREQUESTINFORMATIONW.Request was remapped to enum Windows.Win32.Storage.FileSystem.NtmsOpreqCommand (type int, size 4) but the original field was of type DWORD (size 4).
NTMS_PARTITIONINFORMATIONA in Fs.modified.cs: NTMS_PARTITIONINFORMATIONA.State was remapped to enum Windows.Win32.Storage.FileSystem.NtmsPartitionState (type int, size 4) but the original field was of type DWORD (size 4).
NTMS_PARTITIONINFORMATIONW in Fs.modified.cs: NTMS_PARTITIONINFORMATIONW.State was remapped to enum Windows.Win32.Storage.FileSystem.NtmsPartitionState (type int, size 4) but the original field was of type DWORD (size 4).
NTMS_PMIDINFORMATIONA in Fs.modified.cs: NTMS_PMIDINFORMATIONA.BarCodeState was remapped to enum Windows.Win32.Storage.FileSystem.NtmsBarCodeState (type int, size 4) but the original field was of type DWORD (size 4).
NTMS_PMIDINFORMATIONW in Fs.modified.cs: NTMS_PMIDINFORMATIONW.BarCodeState was remapped to enum Windows.Win32.Storage.FileSystem.NtmsBarCodeState (type int, size 4) but the original field was of type DWORD (size 4).
OLECMD in ComOle.modified.cs: OLECMD.cmdID was remapped to enum Windows.Win32.System.Ole.OLECMDID (type int, size 4) but the original field was of type ULONG (size 4).
OleCreate.renderopt was remapped to enum Windows.Win32.System.Ole.OLERENDER (type int, size 4) but the original field was of type DWORD (size 4).
OLEVERB in ComOle.modified.cs: OLEVERB.grfAttribs was remapped to enum Windows.Win32.System.Ole.OLEVERBATTRIB (type int, size 4) but the original field was of type DWORD (size 4).
PIXELFORMATDESCRIPTOR in Gdi.modified.cs: PIXELFORMATDESCRIPTOR.iLayerType was remapped to enum Windows.Win32.Graphics.OpenGL.PFD_LAYER_TYPE (type sbyte, size 1) but the original field was of type BYTE (size 1).
PRINTER_OPTIONSA in Printing.modified.cs: PRINTER_OPTIONSA.dwFlags was remapped to enum Windows.Win32.Graphics.Printing.PRINTER_OPTION_FLAGS (type int, size 4) but the original field was of type DWORD (size 4).
PRINTER_OPTIONSW in Printing.modified.cs: PRINTER_OPTIONSW.dwFlags was remapped to enum Windows.Win32.Graphics.Printing.PRINTER_OPTION_FLAGS (type int, size 4) but the original field was of type DWORD (size 4).
QACONTAINER in ComOle.modified.cs: QACONTAINER.dwAmbientFlags was remapped to enum Windows.Win32.System.Ole.QACONTAINERFLAGS (type int, size 4) but the original field was of type DWORD (size 4).
QACONTROL in ComOle.modified.cs: QACONTROL.dwMiscStatus was remapped to enum Windows.Win32.System.Ole.OLEMISC (type int, size 4) but the original field was of type DWORD (size 4).
RegDisableReflectionKey.return was remapped to enum Windows.Win32.Foundation.WIN32_ERROR (type uint, size 4) but the original field was of type LONG (size 4).
RemSTGMEDIUM in Com.modified.cs: RemSTGMEDIUM.tymed was remapped to enum Windows.Win32.System.Com.TYMED (type int, size 4) but the original field was of type DWORD (size 4).
SHDESCRIPTIONID in Shell.modified.cs: SHDESCRIPTIONID.dwDescriptionId was remapped to enum Windows.Win32.UI.Shell.SHDID_ID (type int, size 4) but the original field was of type DWORD (size 4).
SHGetKnownFolderPath.dwFlags was remapped to enum Windows.Win32.UI.Shell.KNOWN_FOLDER_FLAG (type int, size 4) but the original field was of type DWORD (size 4).
SnmpSvcSetLogType.nLogType was remapped to enum Windows.Win32.NetworkManagement.Snmp.SNMP_OUTPUT_LOG_TYPE (type uint, size 4) but the original field was of type INT (size 4).
STATSTG in Com.modified.cs: STATSTG.grfLocksSupported was remapped to enum Windows.Win32.System.Com.LOCKTYPE (type int, size 4) but the original field was of type DWORD (size 4).
STGMEDIUM in Com.modified.cs: STGMEDIUM.tymed was remapped to enum Windows.Win32.System.Com.TYMED (type int, size 4) but the original field was of type DWORD (size 4).
SymGetHomeDirectory.type was remapped to enum Windows.Win32.System.Diagnostics.Debug.IMAGEHLP_HD_TYPE (type int, size 4) but the original field was of type DWORD (size 4).
VerifierEnumerateResource.ResourceType was remapped to enum Windows.Win32.System.ApplicationVerifier.eAvrfResourceTypes (type int, size 4) but the original field was of type ULONG (size 4).
VS_FIXEDFILEINFO in Fs.modified.cs: VS_FIXEDFILEINFO.dwFileType was remapped to enum Windows.Win32.Storage.FileSystem.VS_FIXEDFILEINFO_FILE_TYPE (type int, size 4) but the original field was of type DWORD (size 4).
WINDOWPLACEMENT in MenuRc.modified.cs: WINDOWPLACEMENT.showCmd was remapped to enum Windows.Win32.UI.WindowsAndMessaging.SHOW_WINDOW_CMD (type int, size 4) but the original field was of type UINT (size 4).

@mikebattista
Copy link
Contributor

CoRegisterClassObject.flags was remapped to enum Windows.Win32.System.Com.REGCLS (type int, size 4) but the original field was of type DWORD (size 4)
D3D11_BUFFER_DESC in Direct3D11.modified.cs: D3D11_BUFFER_DESC.CPUAccessFlags was remapped to enum Windows.Win32.Graphics.Direct3D11.D3D11_CPU_ACCESS_FLAG (type int, size 4) but the original field was of type UINT (size 4)
D3D11_TEXTURE1D_DESC in Direct3D11.modified.cs: D3D11_TEXTURE1D_DESC.CPUAccessFlags was remapped to enum Windows.Win32.Graphics.Direct3D11.D3D11_CPU_ACCESS_FLAG (type int, size 4) but the original field was of type UINT (size 4)
D3D11_TEXTURE2D_DESC in Direct3D11.modified.cs: D3D11_TEXTURE2D_DESC.CPUAccessFlags was remapped to enum Windows.Win32.Graphics.Direct3D11.D3D11_CPU_ACCESS_FLAG (type int, size 4) but the original field was of type UINT (size 4)
D3D11_TEXTURE2D_DESC1 in Direct3D11.modified.cs: D3D11_TEXTURE2D_DESC1.CPUAccessFlags was remapped to enum Windows.Win32.Graphics.Direct3D11.D3D11_CPU_ACCESS_FLAG (type int, size 4) but the original field was of type UINT (size 4)
D3D11_TEXTURE3D_DESC in Direct3D11.modified.cs: D3D11_TEXTURE3D_DESC.CPUAccessFlags was remapped to enum Windows.Win32.Graphics.Direct3D11.D3D11_CPU_ACCESS_FLAG (type int, size 4) but the original field was of type UINT (size 4)
D3D11_TEXTURE3D_DESC1 in Direct3D11.modified.cs: D3D11_TEXTURE3D_DESC1.CPUAccessFlags was remapped to enum Windows.Win32.Graphics.Direct3D11.D3D11_CPU_ACCESS_FLAG (type int, size 4) but the original field was of type UINT (size 4)
DOCHOSTUIINFO in MsHtml.modified.cs: DOCHOSTUIINFO.dwDoubleClick was remapped to enum Windows.Win32.Web.MsHtml.DOCHOSTUIDBLCLK (type int, size 4) but the original field was of type DWORD (size 4)
GetBkMode.return was remapped to enum Windows.Win32.Graphics.Gdi.BACKGROUND_MODE (type uint, size 4) but the original field was of type INT (size 4)
GetCurrentPackageFullName.return was remapped to enum Windows.Win32.Foundation.WIN32_ERROR (type uint, size 4) but the original field was of type LONG (size 4)
GetThemeColor.iPropId was remapped to enum Windows.Win32.UI.Controls.THEME_PROPERTY_SYMBOL_ID (type uint, size 4) but the original field was of type INT (size 4)
IAMMultiMediaStream in Media.DShow.modified.cs: IAMMultiMediaStream.AddMediaStream.dwFlags was remapped to enum Windows.Win32.Media.DirectShow.AMMSF_MS_FLAGS (type int, size 4) but the original field was of type DWORD (size 4)
IFolderView in Shell.modified.cs: IFolderView.Items.uFlags was remapped to enum Windows.Win32.UI.Shell._SVGIO (type int, size 4) but the original field was of type UINT (size 4)
IIdentityAdvise in IdentityProvider.modified.cs: IIdentityAdvise.IdentityUpdated.dwIdentityUpdateEvents was remapped to enum Windows.Win32.Security.Authentication.Identity.Provider.IdentityUpdateEvent (type int, size 4) but the original field was of type DWORD (size 4)
IIdentityProvider in IdentityProvider.modified.cs: IIdentityProvider.Advise.dwIdentityUpdateEvents was remapped to enum Windows.Win32.Security.Authentication.Identity.Provider.IdentityUpdateEvent (type int, size 4) but the original field was of type DWORD (size 4)
ILockBytes in Com.modified.cs: ILockBytes.Stat.grfStatFlag was remapped to enum Windows.Win32.System.Com.STATFLAG (type int, size 4) but the original field was of type DWORD (size 4)
IOleClientSite in ComOle.modified.cs: IOleClientSite.GetMoniker.dwWhichMoniker was remapped to enum Windows.Win32.System.Ole.OLEWHICHMK (type int, size 4) but the original field was of type DWORD (size 4)
IOleObject in ComOle.modified.cs: IOleObject.SetMoniker.dwWhichMoniker was remapped to enum Windows.Win32.System.Ole.OLEWHICHMK (type int, size 4) but the original field was of type DWORD (size 4)
IRecordInfo in ComOle.modified.cs: IRecordInfo.PutFieldNoCopy.wFlags was remapped to enum Windows.Win32.System.Com.INVOKEKIND (type int, size 4) but the original field was of type ULONG (size 4)
IShellFolderViewCB in Shell.modified.cs: IShellFolderViewCB.MessageSFVCB.uMsg was remapped to enum Windows.Win32.UI.Shell.SFVM_MESSAGE_ID (type int, size 4) but the original field was of type UINT (size 4)
IStorage in Com.modified.cs: IStorage.Stat.grfStatFlag was remapped to enum Windows.Win32.System.Com.STATFLAG (type int, size 4) but the original field was of type DWORD (size 4)
IStream in Com.modified.cs: IStream.LockRegion.dwLockType was remapped to enum Windows.Win32.System.Com.LOCKTYPE (type int, size 4) but the original field was of type DWORD (size 4)
LdapMapErrorToWin32.LdapError was remapped to enum Windows.Win32.Networking.Ldap.LDAP_RETCODE (type int, size 4) but the original field was of type ULONG (size 4)
MsiReinstallProductA.szReinstallMode was remapped to enum Windows.Win32.System.ApplicationInstallationAndServicing.REINSTALLMODE (type int, size 4) but the original field was of type DWORD (size 4)
NTMS_IEPORTINFORMATION in Fs.modified.cs: NTMS_IEPORTINFORMATION.Position was remapped to enum Windows.Win32.Storage.FileSystem.NtmsPortPosition (type int, size 4) but the original field was of type DWORD (size 4)
NTMS_LIBRARYINFORMATION in Fs.modified.cs: NTMS_LIBRARYINFORMATION.InventoryMethod was remapped to enum Windows.Win32.Storage.FileSystem.NtmsInventoryMethod (type int, size 4) but the original field was of type DWORD (size 4)
NTMS_LIBREQUESTINFORMATIONA in Fs.modified.cs: NTMS_LIBREQUESTINFORMATIONA.State was remapped to enum Windows.Win32.Storage.FileSystem.NtmsLmState (type int, size 4) but the original field was of type DWORD (size 4)
NTMS_LIBREQUESTINFORMATIONW in Fs.modified.cs: NTMS_LIBREQUESTINFORMATIONW.State was remapped to enum Windows.Win32.Storage.FileSystem.NtmsLmState (type int, size 4) but the original field was of type DWORD (size 4)
NTMS_OBJECTINFORMATIONA in Fs.modified.cs: NTMS_OBJECTINFORMATIONA.dwOperationalState was remapped to enum Windows.Win32.Storage.FileSystem.NtmsOperationalState (type int, size 4) but the original field was of type DWORD (size 4)
NTMS_OBJECTINFORMATIONW in Fs.modified.cs: NTMS_OBJECTINFORMATIONW.dwOperationalState was remapped to enum Windows.Win32.Storage.FileSystem.NtmsOperationalState (type int, size 4) but the original field was of type DWORD (size 4)
NTMS_OPREQUESTINFORMATIONA in Fs.modified.cs: NTMS_OPREQUESTINFORMATIONA.State was remapped to enum Windows.Win32.Storage.FileSystem.NtmsOpreqState (type int, size 4) but the original field was of type DWORD (size 4)
NTMS_OPREQUESTINFORMATIONW in Fs.modified.cs: NTMS_OPREQUESTINFORMATIONW.State was remapped to enum Windows.Win32.Storage.FileSystem.NtmsOpreqState (type int, size 4) but the original field was of type DWORD (size 4)
NTMS_PMIDINFORMATIONA in Fs.modified.cs: NTMS_PMIDINFORMATIONA.MediaState was remapped to enum Windows.Win32.Storage.FileSystem.NtmsMediaState (type int, size 4) but the original field was of type DWORD (size 4)
NTMS_PMIDINFORMATIONW in Fs.modified.cs: NTMS_PMIDINFORMATIONW.MediaState was remapped to enum Windows.Win32.Storage.FileSystem.NtmsMediaState (type int, size 4) but the original field was of type DWORD (size 4)
OLECMD in ComOle.modified.cs: OLECMD.cmdf was remapped to enum Windows.Win32.System.Ole.OLECMDF (type int, size 4) but the original field was of type DWORD (size 4)
OleRegGetUserType.dwFormOfType was remapped to enum Windows.Win32.System.Ole.USERCLASSTYPE (type int, size 4) but the original field was of type DWORD (size 4)
QACONTROL in ComOle.modified.cs: QACONTROL.dwViewStatus was remapped to enum Windows.Win32.System.Ole.VIEWSTATUS (type int, size 4) but the original field was of type DWORD (size 4)
QueryDisplayConfig.return was remapped to enum Windows.Win32.Foundation.WIN32_ERROR (type uint, size 4) but the original field was of type LONG (size 4)
RegEnableReflectionKey.return was remapped to enum Windows.Win32.Foundation.WIN32_ERROR (type uint, size 4) but the original field was of type LONG (size 4)
SHChangeNotify.wEventId was remapped to enum Windows.Win32.UI.Shell.SHCNE_ID (type uint, size 4) but the original field was of type LONG (size 4)
SymGetSymbolFile.Type was remapped to enum Windows.Win32.System.Diagnostics.Debug.IMAGEHLP_SF_TYPE (type int, size 4) but the original field was of type DWORD (size 4)
VS_FIXEDFILEINFO in Fs.modified.cs: VS_FIXEDFILEINFO.dwFileSubtype was remapped to enum Windows.Win32.Storage.FileSystem.VS_FIXEDFILEINFO_FILE_SUBTYPE (type int, size 4) but the original field was of type DWORD (size 4)

@mikebattista
Copy link
Contributor

CoInitializeSecurity.dwCapabilities was remapped to enum Windows.Win32.System.Com.EOLE_AUTHENTICATION_CAPABILITIES (type int, size 4) but the original field was of type DWORD (size 4)
D3D11_BUFFER_DESC in Direct3D11.modified.cs: D3D11_BUFFER_DESC.MiscFlags was remapped to enum Windows.Win32.Graphics.Direct3D11.D3D11_RESOURCE_MISC_FLAG (type int, size 4) but the original field was of type UINT (size 4)
D3D11_TEXTURE1D_DESC in Direct3D11.modified.cs: D3D11_TEXTURE1D_DESC.MiscFlags was remapped to enum Windows.Win32.Graphics.Direct3D11.D3D11_RESOURCE_MISC_FLAG (type int, size 4) but the original field was of type UINT (size 4)
D3D11_TEXTURE2D_DESC in Direct3D11.modified.cs: D3D11_TEXTURE2D_DESC.MiscFlags was remapped to enum Windows.Win32.Graphics.Direct3D11.D3D11_RESOURCE_MISC_FLAG (type int, size 4) but the original field was of type UINT (size 4)
D3D11_TEXTURE2D_DESC1 in Direct3D11.modified.cs: D3D11_TEXTURE2D_DESC1.MiscFlags was remapped to enum Windows.Win32.Graphics.Direct3D11.D3D11_RESOURCE_MISC_FLAG (type int, size 4) but the original field was of type UINT (size 4)
D3D11_TEXTURE3D_DESC in Direct3D11.modified.cs: D3D11_TEXTURE3D_DESC.MiscFlags was remapped to enum Windows.Win32.Graphics.Direct3D11.D3D11_RESOURCE_MISC_FLAG (type int, size 4) but the original field was of type UINT (size 4)
D3D11_TEXTURE3D_DESC1 in Direct3D11.modified.cs: D3D11_TEXTURE3D_DESC1.MiscFlags was remapped to enum Windows.Win32.Graphics.Direct3D11.D3D11_RESOURCE_MISC_FLAG (type int, size 4) but the original field was of type UINT (size 4)
GetCurrentObject.type was remapped to enum Windows.Win32.Graphics.Gdi.OBJ_TYPE (type int, size 4) but the original field was of type UINT (size 4)
GetCurrentPackageFamilyName.return was remapped to enum Windows.Win32.Foundation.WIN32_ERROR (type uint, size 4) but the original field was of type LONG (size 4)
GetThemeMetric.iPropId was remapped to enum Windows.Win32.UI.Controls.THEME_PROPERTY_SYMBOL_ID (type uint, size 4) but the original field was of type INT (size 4)
IOleObject in ComOle.modified.cs: IOleObject.GetMoniker.dwAssign was remapped to enum Windows.Win32.System.Ole.OLEGETMONIKER (type int, size 4) but the original field was of type DWORD (size 4)
IStream in Com.modified.cs: IStream.LockRegion.dwLockType was remapped to enum Windows.Win32.System.Com.LOCKTYPE (type int, size 4) but the original field was of type DWORD (size 4)
MsiProvideComponentA.dwInstallMode was remapped to enum Windows.Win32.System.ApplicationInstallationAndServicing.INSTALLMODE (type int, size 4) but the original field was of type DWORD (size 4)
PathCleanupSpec.return was remapped to enum Windows.Win32.UI.Shell.PCS_RET (type uint, size 4) but the original field was of type INT (size 4)
QACONTROL in ComOle.modified.cs: QACONTROL.dwPointerActivationPolicy was remapped to enum Windows.Win32.System.Ole.POINTERINACTIVE (type int, size 4) but the original field was of type DWORD (size 4)
RegQueryReflectionKey.return was remapped to enum Windows.Win32.Foundation.WIN32_ERROR (type uint, size 4) but the original field was of type LONG (size 4)

@mikebattista
Copy link
Contributor

EnableScrollBar.wSBflags was remapped to enum Windows.Win32.UI.WindowsAndMessaging.SCROLLBAR_CONSTANTS (type int, size 4) but the original field was of type UINT (size 4)
GetCurrentObject.type was remapped to enum Windows.Win32.Graphics.Gdi.OBJ_TYPE (type int, size 4) but the original field was of type UINT (size 4)
RegRestoreKeyA.dwFlags was remapped to enum Windows.Win32.System.Registry.REG_RESTORE_KEY_FLAGS (type int, size 4) but the original field was of type DWORD (size 4)
MsiProvideComponentA.dwInstallMode was remapped to enum Windows.Win32.System.ApplicationInstallationAndServicing.INSTALLMODE (type int, size 4) but the original field was of type DWORD (size 4)
PathResolve.fFlags was remapped to enum Windows.Win32.UI.Shell.PRF_FLAGS (type int, size 4) but the original field was of type UINT (size 4)
GetCurrentPackagePath.return was remapped to enum Windows.Win32.Foundation.WIN32_ERROR (type uint, size 4) but the original field was of type LONG (size 4)

@mikebattista
Copy link
Contributor

EnableScrollBar.wArrows was remapped to enum Windows.Win32.UI.Controls.ENABLE_SCROLL_BAR_ARROWS (type int, size 4) but the original field was of type UINT (size 4)
GetDeviceCaps.index was remapped to enum Windows.Win32.Graphics.Gdi.GET_DEVICE_CAPS_INDEX (type uint, size 4) but the original field was of type INT (size 4)
MsiEnumClientsExA.dwContext was remapped to enum Windows.Win32.System.ApplicationInstallationAndServicing.MSIINSTALLCONTEXT (type int, size 4) but the original field was of type DWORD (size 4)
SHObjectProperties.shopObjectType was remapped to enum Windows.Win32.UI.Shell.SHOP_TYPE (type int, size 4) but the original field was of type DWORD (size 4)

@riverar
Copy link
Collaborator

riverar commented Mar 21, 2023

Judging by Mike's scans so far, this change is going to create a lot of churn downstream and anger lots of folks. Probably obvious but will say it anyway: we need to work closely with all the projection authors to make sure what we do here makes sense to everyone and minimize impact.

@mikebattista
Copy link
Contributor

The test keeps revealing new failures with every pass. And we haven't quite figured out how to reference types properly in attributes. See #389.

I'm reluctant to remove all these enum applications until we have the E2E lined up.

Is fixing only the COINIT issue enough to unblock you @timsneath? Or are you just going to run into all of these other issues? Are there workarounds in impacted projections that can be applied in the meantime?

Preserving the types of scraped enums was a good change that unblocked other issues so I don't want to revert that.

mikebattista added a commit that referenced this issue Mar 21, 2023
…s or removing enum mappings for #1502.

The test seems to give up within a given family of issues after the first reported issue. Fixing issues will often reveal other related issues.
@timsneath
Copy link
Contributor Author

timsneath commented Mar 21, 2023 via email

@tannergooding
Copy link
Member

introduce it again later when we'd figured out how to avoid the regression.

The best way, IMO, to avoid the regression is to ensure that there is metadata annotating the "associated enum type" so that tooling can pick that up and continue exposing the "friendly" overload.

Tooling has to minorly churn to process the metadata differently but if it does that it can in turn result in no change to what bindings they're exposing.

I'm skeptical that we should hold all other languages hostage to a C++ idiosyncrasy (when there are so many of them!)

The headers are written in C/C++ and compiled in C/C++ exposing an extern "C" or a C++ native ABI. We are ultimately holden to what they expose because that is what the actual binaries expose. In languages that allow overloading this is particularly prevalent because it further changes the exported signature and presents opportunities for conflicts in the future if the API is versioned with new methods.

You could of course make the "break" in the original C exports included in the Windows SDK, but that risks causing problems for C++ code that is consuming the headers directly. You could move such breaks under some back-compat #ifdef, but that itself likewise has complications.

It's the same reason why you can't trivially go and replace those UINT32 or DWORD with uint32_t and why you can't change out wchar_t for char16_t even though the latter is newer and better matches how the Windows ABI actually uses the former.

@mikebattista
Copy link
Contributor

mikebattista commented Mar 22, 2023

I'm curious to hear from @AArnott and @kennykerr since I believe they updated to the latest metadata. Have you heard customer complaints?

Even though the types of the enums changed, if where they are applied expects the same type (since they're remapped to expect the enum), the majority usage scenario of passing in values from the enum should still work right? The tests have shown that we have several enums applied today that have mismatched types from the original definitions, but that really hasn't impacted anyone. So while the type in the API definition is different from the original header, callers haven't seemed to care.

We could do the work proposed here to preserve the original types from the headers while still allowing projections to present the friendly enums, but I'm still a bit unclear how broken things are today in practice.

@kennykerr
Copy link
Contributor

No complaints from my customers.

@AArnott
Copy link
Member

AArnott commented Mar 28, 2023

No complaints so far from users of the latest CsWin32 either.
But if the metadata takes the proposed changes and adds attributes so that projections can maintain the good experience of enums while having the technically correct ABI, CsWin32 can make the compensating changes.

mikebattista added a commit that referenced this issue May 22, 2023
…'t align (#1572)

* Added test for enum size mismatches and started fixing reported issues or removing enum mappings for #1502.

The test seems to give up within a given family of issues after the first reported issue. Fixing issues will often reveal other related issues.

* Removed or corrected enums with mismatched sizes.

* Added AssociatedEnum attributes.

* Documented AssociatedEnum.

* Fixed bad merge.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants