Skip to content

Commit

Permalink
Fix for non-remotable COM interfaces
Browse files Browse the repository at this point in the history
Fixes #860
  • Loading branch information
AArnott committed Mar 9, 2023
1 parent 93b50df commit 34653a1
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 11 deletions.
3 changes: 2 additions & 1 deletion src/Microsoft.Windows.CsWin32/Generator.FriendlyOverloads.cs
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ private IEnumerable<MethodDeclarationSyntax> DeclareFriendlyOverloads(MethodDefi
if (sizeParamIndex.HasValue
&& externMethodDeclaration.ParameterList.Parameters.Count > sizeParamIndex.Value
&& !(externMethodDeclaration.ParameterList.Parameters[sizeParamIndex.Value].Type is PointerTypeSyntax)
&& !(externMethodDeclaration.ParameterList.Parameters[sizeParamIndex.Value].Modifiers.Any(SyntaxKind.OutKeyword) || externMethodDeclaration.ParameterList.Parameters[sizeParamIndex.Value].Modifiers.Any(SyntaxKind.RefKeyword))
&& !isPointerToPointer)
{
signatureChanged = true;
Expand Down Expand Up @@ -290,7 +291,7 @@ private IEnumerable<MethodDeclarationSyntax> DeclareFriendlyOverloads(MethodDefi

arguments[sizeParamIndex.Value] = Argument(sizeArgExpression);
}
else if (sizeConst.HasValue && !isPointerToPointer && this.canUseSpan)
else if (sizeConst.HasValue && !isPointerToPointer && this.canUseSpan && externParam.Type is PointerTypeSyntax)
{
// TODO: add support for lists of pointers via a generated pointer-wrapping struct
signatureChanged = true;
Expand Down
2 changes: 1 addition & 1 deletion src/Microsoft.Windows.CsWin32/Generator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ void AddSymbolIf(bool condition, string symbol)
this.fieldOfHandleTypeDefTypeSettings = this.generalTypeSettings with { PreferNativeInt = false };
this.externSignatureTypeSettings = this.generalTypeSettings with { QualifyNames = true, PreferMarshaledTypes = options.AllowMarshaling };
this.externReleaseSignatureTypeSettings = this.externSignatureTypeSettings with { PreferNativeInt = false, PreferMarshaledTypes = false };
this.comSignatureTypeSettings = this.generalTypeSettings with { QualifyNames = true };
this.comSignatureTypeSettings = this.generalTypeSettings with { QualifyNames = true, PreferInOutRef = options.AllowMarshaling };
this.extensionMethodSignatureTypeSettings = this.generalTypeSettings with { QualifyNames = true };
this.functionPointerTypeSettings = this.generalTypeSettings with { QualifyNames = true };
this.errorMessageTypeSettings = this.generalTypeSettings with { QualifyNames = true, Generator = null }; // Avoid risk of infinite recursion from errors in ToTypeSyntax
Expand Down
4 changes: 2 additions & 2 deletions src/Microsoft.Windows.CsWin32/PointerTypeHandleInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ internal record PointerTypeHandleInfo(TypeHandleInfo ElementType) : TypeHandleIn

internal override TypeSyntaxAndMarshaling ToTypeSyntax(TypeSyntaxSettings inputs, CustomAttributeHandleCollection? customAttributes, ParameterAttributes parameterAttributes)
{
TypeSyntaxAndMarshaling elementTypeDetails = this.ElementType.ToTypeSyntax(inputs, customAttributes);
if (elementTypeDetails.MarshalAsAttribute is object || inputs.Generator?.IsManagedType(this.ElementType) is true)
TypeSyntaxAndMarshaling elementTypeDetails = this.ElementType.ToTypeSyntax(inputs with { PreferInOutRef = false }, customAttributes);
if (elementTypeDetails.MarshalAsAttribute is object || inputs.Generator?.IsManagedType(this.ElementType) is true || (inputs.PreferInOutRef && this.ElementType is PrimitiveTypeHandleInfo { PrimitiveTypeCode: not PrimitiveTypeCode.Void }))
{
bool xIn = (parameterAttributes & ParameterAttributes.In) == ParameterAttributes.In;
bool xOut = (parameterAttributes & ParameterAttributes.Out) == ParameterAttributes.Out;
Expand Down
2 changes: 1 addition & 1 deletion src/Microsoft.Windows.CsWin32/TypeSyntaxSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@

namespace Microsoft.Windows.CsWin32;

internal record TypeSyntaxSettings(Generator? Generator, bool PreferNativeInt, bool PreferMarshaledTypes, bool AllowMarshaling, bool QualifyNames, bool IsField = false)
internal record TypeSyntaxSettings(Generator? Generator, bool PreferNativeInt, bool PreferMarshaledTypes, bool AllowMarshaling, bool QualifyNames, bool IsField = false, bool PreferInOutRef = false)
{
}
21 changes: 21 additions & 0 deletions test/GenerationSandbox.Tests/ComRuntimeTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using Windows.Win32;
using Windows.Win32.UI.Shell;
using IServiceProvider = Windows.Win32.System.Com.IServiceProvider;

public class ComRuntimeTests
{
[Fact]
public void RemotableInterface()
{
IShellWindows shellWindows = (IShellWindows)new ShellWindows();
IServiceProvider serviceProvider = (IServiceProvider)shellWindows.FindWindowSW(
PInvoke.CSIDL_DESKTOP,
null,
(int)ShellWindowTypeConstants.SWC_DESKTOP,
out int hwnd,
(int)ShellWindowFindWindowOptions.SWFO_NEEDDISPATCH);
}
}
6 changes: 6 additions & 0 deletions test/GenerationSandbox.Tests/NativeMethods.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ BOOLEAN
CHAR
CreateCursor
CreateFile
CSIDL_DESKTOP
DISPLAYCONFIG_VIDEO_SIGNAL_INFO
EnumWindows
GetProcAddress
Expand All @@ -13,6 +14,8 @@ HDC_UserSize
IDirectorySearch
IEnumDebugPropertyInfo
IPersistFile
IServiceProvider
IShellWindows
KEY_EVENT_RECORD
LoadLibrary
MainAVIHeader
Expand All @@ -25,6 +28,9 @@ RECT
RegLoadAppKey
RM_PROCESS_INFO
ShellLink
ShellWindowFindWindowOptions
ShellWindows
ShellWindowTypeConstants
SHFILEOPSTRUCTW
SIZE
VARDESC
Expand Down
19 changes: 13 additions & 6 deletions test/Microsoft.Windows.CsWin32.Tests/COMTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -241,14 +241,21 @@ public void MethodWithHRParameter()
}

[Theory]
[InlineData("IVssCreateWriterMetadata")] // A non-COM compliant interface (since it doesn't derive from IUnknown).
[InlineData("IProtectionPolicyManagerInterop3")] // An IInspectable-derived interface.
[InlineData("ICompositionCapabilitiesInteropFactory")] // An interface with managed types.
[InlineData("IPicture")] // An interface with properties that cannot be represented as properties.
public void InterestingComInterfaces(string api)
[CombinatorialData]
public void InterestingComInterfaces(
[CombinatorialValues(
"IVssCreateWriterMetadata", // A non-COM compliant interface (since it doesn't derive from IUnknown).
"IProtectionPolicyManagerInterop3", // An IInspectable-derived interface.
"ICompositionCapabilitiesInteropFactory", // An interface with managed types.
"IPicture", // An interface with properties that cannot be represented as properties.
"ID2D1DeviceContext2", // CreateLookupTable3D takes fixed length arrays as parameters
"IVPBaseConfig", // GetConnectInfo has a CountParamIndex that points to an [In, Out] parameter.
"IWMDMDevice2")] // The GetSpecifyPropertyPages method has an NativeArrayInfo.CountParamIndex pointing at an [Out] parameter.
string api,
bool allowMarshaling)
{
this.compilation = this.starterCompilations["net6.0"];
this.generator = this.CreateGenerator(DefaultTestGeneratorOptions with { AllowMarshaling = false });
this.generator = this.CreateGenerator(DefaultTestGeneratorOptions with { AllowMarshaling = allowMarshaling });
Assert.True(this.generator.TryGenerate(api, CancellationToken.None));
this.CollectGeneratedCode(this.generator);
this.AssertNoDiagnostics();
Expand Down

0 comments on commit 34653a1

Please sign in to comment.