Skip to content

Commit

Permalink
Merge pull request #201 from microsoft/fix103
Browse files Browse the repository at this point in the history
Add `CoCreateInstance` generic friendly overload
  • Loading branch information
AArnott authored Mar 17, 2021
2 parents f9f0a4c + 5bc4635 commit c5d596c
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 31 deletions.
42 changes: 34 additions & 8 deletions src/Microsoft.Windows.CsWin32/Generator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1231,11 +1231,11 @@ internal void GetBaseTypeInfo(TypeDefinition typeDef, out StringHandle baseTypeN
switch (specialName)
{
case "PCWSTR":
specialDeclaration = this.FetchTemplate($"{specialName}.cs");
specialDeclaration = this.FetchTemplate($"{specialName}");
this.TryGenerateType("PWSTR"); // the template references this type
break;
case "PCSTR":
specialDeclaration = this.FetchTemplate($"{specialName}.cs");
specialDeclaration = this.FetchTemplate($"{specialName}");
this.TryGenerateType("PSTR"); // the template references this type
break;
default:
Expand Down Expand Up @@ -1888,17 +1888,28 @@ private static ObjectCreationExpressionSyntax PropertyKeyValue(CustomAttribute p

private MemberDeclarationSyntax FetchTemplate(string name)
{
using Stream? templateStream = Assembly.GetExecutingAssembly().GetManifestResourceStream($"{ThisAssembly.RootNamespace}.templates.{name}");
if (templateStream is null)
if (!this.TryFetchTemplate(name, out MemberDeclarationSyntax? result))
{
throw new KeyNotFoundException();
}

return result;
}

private bool TryFetchTemplate(string name, [NotNullWhen(true)] out MemberDeclarationSyntax? member)
{
using Stream? templateStream = Assembly.GetExecutingAssembly().GetManifestResourceStream($"{ThisAssembly.RootNamespace}.templates.{name.Replace('/', '.')}.cs");
if (templateStream is null)
{
member = null;
return false;
}

using StreamReader sr = new(templateStream);
string template = sr.ReadToEnd();
MemberDeclarationSyntax member = ParseMemberDeclaration(template) ?? throw new GenerationFailedException($"Unable to parse a type from a template: {name}");
MemberDeclarationSyntax memberWithVisibility = this.ElevateVisibility(member);
return memberWithVisibility;
member = ParseMemberDeclaration(template) ?? throw new GenerationFailedException($"Unable to parse a type from a template: {name}");
member = this.ElevateVisibility(member);
return true;
}

private FunctionPointerTypeSyntax FunctionPointer(MethodDefinition methodDefinition, MethodSignature<TypeHandleInfo> signature)
Expand Down Expand Up @@ -2899,7 +2910,7 @@ private StructDeclarationSyntax DeclareTypeDefStruct(TypeDefinition typeDef)
return result;
}

private IEnumerable<MemberDeclarationSyntax> ExtractMembersFromTemplate(string name) => ((TypeDeclarationSyntax)this.FetchTemplate($"{name}.cs")).Members;
private IEnumerable<MemberDeclarationSyntax> ExtractMembersFromTemplate(string name) => ((TypeDeclarationSyntax)this.FetchTemplate($"{name}")).Members;

/// <summary>
/// Promotes an <see langword="internal" /> member to be <see langword="public"/> if <see cref="Visibility"/> indicates that generated APIs should be public.
Expand Down Expand Up @@ -3161,6 +3172,21 @@ private EnumDeclarationSyntax DeclareEnum(TypeDefinition typeDef)

private IEnumerable<MethodDeclarationSyntax> DeclareFriendlyOverloads(MethodDefinition methodDefinition, MethodDeclarationSyntax externMethodDeclaration, string declaringTypeName, FriendlyOverloadOf overloadOf)
{
if (this.TryFetchTemplate(externMethodDeclaration.Identifier.ValueText, out MemberDeclarationSyntax? templateFriendlyOverload))
{
yield return (MethodDeclarationSyntax)templateFriendlyOverload;
}

if (this.options.AllowMarshaling && this.TryFetchTemplate("marshaling/" + externMethodDeclaration.Identifier.ValueText, out templateFriendlyOverload))
{
yield return (MethodDeclarationSyntax)templateFriendlyOverload;
}

if (!this.options.AllowMarshaling && this.TryFetchTemplate("no_marshaling/" + externMethodDeclaration.Identifier.ValueText, out templateFriendlyOverload))
{
yield return (MethodDeclarationSyntax)templateFriendlyOverload;
}

#pragma warning disable SA1114 // Parameter list should follow declaration
static ParameterSyntax StripAttributes(ParameterSyntax parameter) => parameter.WithAttributeLists(List<AttributeListSyntax>());
static ExpressionSyntax GetSpanLength(ExpressionSyntax span) => MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, span, IdentifierName(nameof(Span<int>.Length)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
</ItemGroup>

<ItemGroup>
<Compile Remove="templates\*.cs" />
<Compile Remove="templates\**\*.cs" />
</ItemGroup>

<ItemGroup>
Expand All @@ -35,7 +35,7 @@
</ItemGroup>

<ItemGroup>
<EmbeddedResource Include="templates\*.cs" />
<EmbeddedResource Include="templates\**\*.cs" />
<EmbeddedResource Include="@(YamlDocOutputPath)" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/// <inheritdoc cref="CoCreateInstance(Guid*, object, uint, Guid*, out object)"/>
internal static unsafe HRESULT CoCreateInstance<T>(in Guid rclsid, object pUnkOuter, uint dwClsContext, out T ppv)
where T : class
{
HRESULT hr = CoCreateInstance(rclsid, pUnkOuter, dwClsContext, typeof(T).GUID, out object o);
ppv = (T)o;
return hr;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/// <inheritdoc cref="CoCreateInstance(Guid*, IUnknown*, uint, Guid*, void**)"/>
internal static unsafe HRESULT CoCreateInstance<T>(in Guid rclsid, IUnknown* pUnkOuter, uint dwClsContext, out T* ppv)
where T : unmanaged
{
HRESULT hr = CoCreateInstance(rclsid, pUnkOuter, dwClsContext, typeof(T).GUID, out void* o);
ppv = (T*)o;
return hr;
}
1 change: 1 addition & 0 deletions test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ public void InterestingAPIs(
"D3D11_BLEND_DESC1", // nested structs with inline arrays with element that is NOT nested
"RTM_DEST_INFO", // nested structs with inline arrays with element whose name collides with another
"DISPPARAMS",
"CoCreateInstance", // a hand-written friendly overload
"JsVariantToValue",
"WIA_CATEGORY_FINISHED_FILE", // GUID constant
"DEVPKEY_MTPBTH_IsConnected", // PROPERTYKEY constant
Expand Down
20 changes: 0 additions & 20 deletions test/SpellChecker/PInvoke.cs

This file was deleted.

2 changes: 1 addition & 1 deletion test/SpellChecker/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
typeof(SpellCheckerFactory).GUID,
null,
(uint)CLSCTX.CLSCTX_INPROC_SERVER, // https://github.com/microsoft/win32metadata/issues/185
out ISpellCheckerFactory spellCheckerFactory);
out ISpellCheckerFactory spellCheckerFactory).ThrowOnFailure();

BOOL supported = spellCheckerFactory.IsSupported("en-US");

Expand Down

0 comments on commit c5d596c

Please sign in to comment.