microsoft / win32metadata

Tooling to generate metadata for Win32 APIs in the Windows SDK.
Other
1.31k stars 116 forks source link

There are many APIs that are exported as `stdcall` but are now declared to be `cdecl` #1217

Closed kennykerr closed 1 year ago

kennykerr commented 1 year ago

There are a lot more now cdecl that aren't in the real DLLs (probably incomplete list):

``` __imp__WTSEnableChildSessions __imp__WTSGetChildSessionId __imp__WTSIsChildSessionsEnabled __imp__CreatePrinterIC __imp__DeletePrinterIC __imp__ExtDeviceMode __imp__PlayGdiScriptOnPrinterIC __imp__RouterFreeBidiResponseContainer __imp__DoConnectoidsExist __imp__IsProfilesEnabled __imp__PerformOperationOverUrlCacheA __imp__UrlCacheFreeGlobalSpace __imp__UrlCacheGetGlobalCacheSize __imp__WerFreeString __imp__WerStoreClose __imp__WerStoreGetFirstReportKey __imp__WerStoreGetNextReportKey __imp__WerStoreGetReportCount __imp__WerStoreGetSizeOnDisk __imp__WerStoreOpen __imp__WerStorePurge __imp__WerStoreQueryReportMetadataV1 __imp__WerStoreQueryReportMetadataV2 __imp__WerStoreQueryReportMetadataV3 __imp__WerStoreUploadReport __imp__PxeProviderFreeInfo __imp__GetDeviceIDString __imp__SrpIsTokenService __imp__AppendPrinterNotifyInfoData __imp__CallRouterFindFirstPrinterChangeNotification __imp__GetJobAttributesEx __imp__ImpersonatePrinterClient __imp__PartialReplyPrinterChangeNotification __imp__ProvidorFindClosePrinterChangeNotification __imp__ProvidorFindFirstPrinterChangeNotification __imp__ReplyPrinterChangeNotificationEx __imp__RevertToPrinterSelf __imp__RouterAllocBidiMem __imp__RouterAllocBidiResponseContainer __imp__RouterAllocPrinterNotifyInfo __imp__RouterFreeBidiMem __imp__RouterFreePrinterNotifyInfo __imp__SplIsSessionZero __imp__SplPromptUIInUsersSession __imp__SpoolerFindClosePrinterChangeNotification __imp__SpoolerFindFirstPrinterChangeNotification __imp__SpoolerFindNextPrinterChangeNotification __imp__SpoolerFreePrinterNotifyInfo __imp__SpoolerRefreshPrinterChangeNotification __imp__CollectionsListAllocateBufferAndSerialize __imp__CollectionsListCopyAndMarshall __imp__CollectionsListDeserializeFromBuffer __imp__CollectionsListGetFillableCount __imp__CollectionsListGetMarshalledSizeWithoutSerialization __imp__CollectionsListGetSerializedSize __imp__CollectionsListMarshall __imp__CollectionsListSerializeToBuffer __imp__CollectionsListSortSubscribedActivitiesByConfidence __imp__CollectionsListUpdateMarshalledPointer __imp__EvaluateActivityThresholds __imp__GetPerformanceTime __imp__InitPropVariantFromCLSIDArray __imp__InitPropVariantFromFloat __imp__IsCollectionListSame __imp__IsGUIDPresentInList __imp__IsKeyPresentInCollectionList __imp__IsKeyPresentInPropertyList __imp__IsSensorSubscribed __imp__PropKeyFindKeyGetBool __imp__PropKeyFindKeyGetDouble __imp__PropKeyFindKeyGetFileTime __imp__PropKeyFindKeyGetFloat __imp__PropKeyFindKeyGetGuid __imp__PropKeyFindKeyGetInt32 __imp__PropKeyFindKeyGetInt64 __imp__PropKeyFindKeyGetNthInt64 __imp__PropKeyFindKeyGetNthUlong __imp__PropKeyFindKeyGetNthUshort __imp__PropKeyFindKeyGetPropVariant __imp__PropKeyFindKeyGetUlong __imp__PropKeyFindKeyGetUshort __imp__PropKeyFindKeySetPropVariant __imp__PropVariantGetInformation __imp__PropertiesListCopy __imp__PropertiesListGetFillableCount __imp__SensorCollectionGetAt __imp__SerializationBufferAllocate __imp__SerializationBufferFree __imp__AcceptSecurityContext@40 __imp__CredMarshalTargetInfo __imp__CredUnmarshalTargetInfo __imp__InitializeSecurityContextA@52 __imp__InitializeSecurityContextW@52 __imp__SaslAcceptSecurityContext@40 __imp__SaslInitializeSecurityContextA@52 __imp__SaslInitializeSecurityContextW@52 __imp__LogErrorW __imp__LogEventW __imp__RouterAssert __imp__RouterGetErrorStringA __imp__RouterGetErrorStringW __imp__RouterLogDeregisterA __imp__RouterLogDeregisterW __imp__RouterLogEventA __imp__RouterLogEventDataA __imp__RouterLogEventDataW __imp__RouterLogEventStringA __imp__RouterLogEventStringW __imp__RouterLogEventValistExA __imp__RouterLogEventValistExW __imp__RouterLogEventW __imp__RouterLogRegisterA __imp__RouterLogRegisterW __imp__MgmAddGroupMembershipEntry __imp__MgmDeRegisterMProtocol __imp__MgmDeleteGroupMembershipEntry __imp__MgmGetFirstMfeStats __imp__MgmGetMfeStats __imp__MgmGetNextMfeStats __imp__MgmGetProtocolOnInterface __imp__MgmGroupEnumerationEnd __imp__MgmGroupEnumerationGetNext __imp__MgmGroupEnumerationStart __imp__MgmRegisterMProtocol __imp__MgmReleaseInterfaceOwnership __imp__MgmTakeInterfaceOwnership __imp__RtmConvertIpv6AddressAndLengthToNetAddress __imp__RtmConvertNetAddressToIpv6AddressAndLength __imp__I_RpcServerInqAddressChangeFn __imp__ClusWorkersTerminate __imp__FreeClusterHealthFaultArray __imp__InitializeClusterHealthFaultArray __imp__ResUtilLeftPaxosIsLessThanRight __imp__ResUtilPaxosComparer __imp__ResUtilsDeleteKeyTree __imp__NetAddServiceAccount __imp__NetEnumerateServiceAccounts __imp__NetIsServiceAccount __imp__NetQueryServiceAccount __imp__NetRemoveServiceAccount __imp__DestroyIndexedResults __imp__DestroyResourceIndexer __imp__WNetSetLastErrorA __imp__WNetSetLastErrorW __imp__BackupPerfRegistryToFileW __imp__RestorePerfRegistryFromFileW __imp__GetCurrentClockTransactionManager __imp__GetTransactionManagerId __imp__KeyCredentialManagerFreeInformation __imp__GetOwnerModuleFromPidAndInfo __imp__DnsConnectionDeleteProxyInfo __imp__DnsConnectionFreeNameList __imp__DnsConnectionFreeProxyInfoEx __imp__DnsConnectionFreeProxyList __imp__DnsConnectionGetNameList __imp__DnsConnectionGetProxyInfoForHostUrl __imp__DnsConnectionGetProxyList __imp__DnsConnectionSetProxyInfo __imp__DnsConnectionUpdateIfIndexTable __imp__DnsRecordSetDetach __imp__DnsValidateName_A __imp__DnsValidateName_UTF8 __imp__DnsValidateName_W __imp__DhcpAddServer __imp__DhcpAuditLogGetParams __imp__DhcpAuditLogSetParams __imp__DhcpCreateOptionV5 __imp__DhcpDeleteServer __imp__DhcpDeleteSuperScopeV4 __imp__DhcpDsCleanup __imp__DhcpDsInit __imp__DhcpEnumOptionValuesV5 __imp__DhcpEnumOptionsV5 __imp__DhcpEnumServers __imp__DhcpGetClassInfo __imp__DhcpGetMibInfoV6 __imp__DhcpGetOptionInfoV5 __imp__DhcpGetOptionValueV5 __imp__DhcpGetOptionValueV6 __imp__DhcpGetSuperScopeInfoV4 __imp__DhcpGetThreadOptions __imp__DhcpHlprFindV4DhcpProperty __imp__DhcpRemoveOptionV5 __imp__DhcpRemoveOptionValueV5 __imp__DhcpServerBackupDatabase __imp__DhcpServerQueryAttributes __imp__DhcpServerQueryDnsRegCredentials __imp__DhcpServerRedoAuthorization __imp__DhcpServerRestoreDatabase __imp__DhcpServerSetDnsRegCredentialsV5 __imp__DhcpSetOptionInfoV5 __imp__DhcpSetOptionValueV5 __imp__DhcpSetOptionValuesV5 __imp__DhcpSetSubnetInfoV6 __imp__DhcpSetSuperScopeV4 __imp__DhcpSetThreadOptions __imp__NetworkIsolationDiagnoseConnectFailureAndGetInfo __imp__NetworkIsolationEnumAppContainers __imp__NetworkIsolationFreeAppContainers __imp__NetworkIsolationGetAppContainerConfig __imp__NetworkIsolationRegisterForAppContainerChanges __imp__NetworkIsolationSetAppContainerConfig __imp__NetworkIsolationSetupAppContainerBinaries __imp__NetworkIsolationUnregisterForAppContainerChanges __imp__GetFeatureVariant __imp__GetFeatureEnabledState __imp__RecordFeatureError __imp__RecordFeatureUsage __imp__SubscribeFeatureStateChangeNotification __imp__UnsubscribeFeatureStateChangeNotification __imp__TraceMessageVa ```

Originally posted by @glandium in https://github.com/microsoft/windows-rs/issues/1999#issuecomment-1234848804

riverar commented 1 year ago

@tannergooding Can you confirm ClangSharp doesn't have the ability to set a default calling convention? It seems you can either choose to remap everything and lose all calling convention attribute output (--with-callconv *=Winapi) or choose to remap nothing and ClangSharp defaults to Cdecl.

Think we need a --default-callconv to override the defaults in ClangSharp?

sotteson1 commented 1 year ago

Maybe there’s an option we can give to clang. Unfortunately I’m out of town until Sunday so I can’t try it until then.

riverar commented 1 year ago

@sotteson1 Good idea, will look now.

riverar commented 1 year ago

I changed base settings for all archs as follows:

With the hopes that x64/arm64 passes would simply drop the calling convention (but after grouping them during cross-arch operations since I mapped them all to stdcall). But this resulted in all the functions getting marked stdcall again regardless of architecture. I think there's some additional work needed to make this all work on our side.

No fast fix here, see you Sunday/Monday.

tannergooding commented 1 year ago

The actual issue here is that Clang doesn't surface any calling convention information for x64 (outside vectorcall and varargs) because there isn't any other convention. As far as x64 windows is concerned, cdecl == stdcall == fastcall.

For 32-bit this matters, but Clang only surfaces that when the file was processed for -m32 (rather than -m64). There are some downside of processing as -m32 as well, such as various other defines/definitions being incorrect in certain edge cases.

However, processing as both -m32 and -m64 to observe the differences and then manually specify --with-callconv name=cdecl in the few places that aren't stdcall and to catch any structs where the layout is truly different between 32-bit/64-bit might be a good idea anyways.

I know one example where the 32-bit vs 64-bit layouts are incompatible is um/commctrl.h for TBBUTTON. IIRC there were others in setupapi and a couple other headers as well.

sotteson1 commented 1 year ago

We scan multiple times for x86 (using -m32) and x64/arm64 (using -m64), although if we previously detected they were all equivalent for a partition (a set of headers) we only scan once using x64. So maybe to detect calling convention, we need to scan the “common” ones using x86 (-m32). Would that get us the information we need?

tannergooding commented 1 year ago

That should. Clang supports (and has tests) covering that the default calling convention detection works as expected for -m32.

Having a --with-callconv *=stdcall will prevent that from working, however. I could probably add something that reports a warning/error if targeting 32-bit and the override doesn't match -or- some special switch to state the default should be x without overriding other cases. Would need to double check on the latter case, however, as I think "default" reports as cdecl for x64 Windows.