Skip to content

Commit 9a5f66f

Browse files
committed
Project flexible arrays as Span<byte>
1 parent d531fc7 commit 9a5f66f

File tree

2 files changed

+19
-4
lines changed

2 files changed

+19
-4
lines changed

src/Microsoft.Windows.CsWin32/Generator.FriendlyOverloads.cs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,8 @@ private IEnumerable<MethodDeclarationSyntax> DeclareFriendlyOverload(
198198
bool isManagedParameterType = this.IsManagedType(parameterTypeInfo);
199199
MemorySize? memorySize = null;
200200
bool mustRemainAsPointer = false;
201+
bool isArray = false;
202+
bool projectAsSpanBytes = false;
201203
bool isPointerToStructWithFlexibleArray = parameterTypeInfo is PointerTypeHandleInfo { ElementType: HandleTypeHandleInfo pointedElement } && pointedElement.Generator.IsStructWithFlexibleArray(pointedElement);
202204
if (this.FindInteropDecorativeAttribute(paramAttributes, MemorySizeAttribute) is CustomAttribute memorySizeAttribute)
203205
{
@@ -214,7 +216,20 @@ private IEnumerable<MethodDeclarationSyntax> DeclareFriendlyOverload(
214216
else if (memorySize is null)
215217
{
216218
// If there's no MemorySize attribute, we may still need to keep this parameter as a pointer if it's a struct with a flexible array.
217-
mustRemainAsPointer = isPointerToStructWithFlexibleArray;
219+
if (isPointerToStructWithFlexibleArray)
220+
{
221+
if (improvePointersToSpansAndRefs)
222+
{
223+
// FlexibleSizeArrays are easier to work with if they project as Span<byte>. Callers can request the pointer verions
224+
// via FriendlyOverloads.IncludePointerOverloads = true.
225+
isArray = true;
226+
projectAsSpanBytes = true;
227+
}
228+
else
229+
{
230+
mustRemainAsPointer = true;
231+
}
232+
}
218233
}
219234
else if (!improvePointersToSpansAndRefs)
220235
{
@@ -239,7 +254,6 @@ private IEnumerable<MethodDeclarationSyntax> DeclareFriendlyOverload(
239254

240255
IdentifierNameSyntax origName = IdentifierName(externParam.Identifier.ValueText);
241256

242-
bool isArray = false;
243257
bool isNullTerminated = false; // TODO
244258
bool isCountOfBytes = false;
245259
short? countParamIndex = null;
@@ -273,7 +287,6 @@ private IEnumerable<MethodDeclarationSyntax> DeclareFriendlyOverload(
273287
isCountOfBytes = true;
274288
}
275289

276-
bool projectAsSpanBytes = false;
277290
if (improvePointersToSpansAndRefs && IsVoidPtrOrPtrPtr(externParam.Type))
278291
{
279292
// if it's memory-sized project as Span<byte>
@@ -1002,7 +1015,7 @@ bool TryHandleCountParam(TypeSyntax elementType, bool nullableSource)
10021015
if (externParam.Type is PointerTypeSyntax)
10031016
{
10041017
remainsRefType = false;
1005-
if (isCountOfBytes)
1018+
if (isCountOfBytes || isPointerToStructWithFlexibleArray)
10061019
{
10071020
// For parameters annotated as count of bytes, we need to switch the friendly parameter to Span<byte>
10081021
// and then cast to (ParamType*) when we call the p/invoke.

test/CsWin32Generator.Tests/CsWin32GeneratorTests.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,8 @@ public async Task PointerReturnValueIsPreserved()
209209
["CancelIoEx", "CancelIoEx", "SafeHandle hFile, global::System.Threading.NativeOverlapped* lpOverlapped"],
210210
["ITypeInfo", "GetNames", "this winmdroot.System.Com.ITypeInfo @this, int memid, Span<winmdroot.Foundation.BSTR> rgBstrNames, out uint pcNames"],
211211
["EnumProcessModules", "EnumProcessModules", "SafeHandle hProcess, Span<byte> lphModule, out uint lpcbNeeded"],
212+
["AdjustTokenPrivileges", "AdjustTokenPrivileges", "SafeHandle TokenHandle, winmdroot.Foundation.BOOL DisableAllPrivileges, Span<byte> NewState, Span<byte> PreviousState, out uint ReturnLength"],
213+
["IMAPIStatus", "FlushQueues", "nuint ulUIParam, ReadOnlySpan<byte> lpTargetTransport, uint ulFlags"],
212214
];
213215

214216
[Theory]

0 commit comments

Comments
 (0)