Friendly overload should preserve null terminator for ref Span<char>
parameters #1295
Description
I am trying to work with CryptCATCDFEnumMembersByCDFTagEx, which enumerates file members in the CatalogFiles
section of a catalog definition file (CDF). Support for this is newly added since Microsoft.Windows.SDK.Win32Metadata 62.0.23-preview
.
The original API syntax is:
LPWSTR WINAPI CryptCATCDFEnumMembersByCDFTagEx(
_In_ CRYPTCATCDF *pCDF,
_Inout_ LPWSTR pwszPrevCDFTag,
_In_ PFN_CDF_PARSE_ERROR_CALLBACK pfnParseError,
_In_ CRYPTCATMEMBER **ppMember,
_In_ BOOL fContinueOnError,
_In_ LPVOID pvReserved
);
The API returns a LPWSTR
string pointer (of a null-terminated string) that identifies a file member in the CatalogFiles
section. To enumerate the entire file, this return value needs to be passed into subsequent calls with parameter pwszPrevCDFTag
, which is also of type LPWSTR
.
The generated code from CsWin32 looks like:
/// <summary>Enumerates catalog-level attributes within the CatalogHeader section of a catalog definition file (CDF).</summary>
/// <param name="pCDF">A pointer to a [CRYPTCATCDF](/windows/desktop/api/mscat/ns-mscat-cryptcatcdf) structure.</param>
/// <param name="pPrevAttr">A pointer to a [CRYPTCATATTRIBUTE](/windows/desktop/api/mscat/ns-mscat-cryptcatattribute) structure for a catalog attribute in the CDF pointed to by <i>pCDF</i>.</param>
/// <param name="pfnParseError">A pointer to a user-defined function to handle file parse errors.</param>
/// <returns>Upon success, this function returns a pointer to a [CRYPTCATATTRIBUTE](/windows/desktop/api/mscat/ns-mscat-cryptcatattribute) structure. The <b>CryptCATCDFEnumCatAttributes</b> function returns a <b>NULL</b> pointer if it fails.</returns>
/// <remarks>You typically call this function in a loop to enumerate all of the catalog header attributes in a CDF. Before entering the loop, set <i>pPrevAttr</i> to <b>NULL</b>. The function returns a pointer to the first attribute. Set <i>pPrevAttr</i> to the return value of the function for subsequent iterations of the loop.</remarks>
[DllImport("WINTRUST.dll", ExactSpelling = true)]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
internal static extern unsafe winmdroot.Security.Cryptography.Catalog.CRYPTCATATTRIBUTE* CryptCATCDFEnumCatAttributes(winmdroot.Security.Cryptography.Catalog.CRYPTCATCDF* pCDF, winmdroot.Security.Cryptography.Catalog.CRYPTCATATTRIBUTE* pPrevAttr, winmdroot.Security.Cryptography.Catalog.PFN_CDF_PARSE_ERROR_CALLBACK pfnParseError);
/// <inheritdoc cref="CryptCATCDFEnumMembersByCDFTagEx(winmdroot.Security.Cryptography.Catalog.CRYPTCATCDF*, winmdroot.Foundation.PWSTR, winmdroot.Security.Cryptography.Catalog.PFN_CDF_PARSE_ERROR_CALLBACK, winmdroot.Security.Cryptography.Catalog.CRYPTCATMEMBER**, winmdroot.Foundation.BOOL, void*)"/>
internal static unsafe winmdroot.Foundation.PWSTR CryptCATCDFEnumMembersByCDFTagEx(in winmdroot.Security.Cryptography.Catalog.CRYPTCATCDF pCDF, ref Span<char>pwszPrevCDFTag, winmdroot.Security.Cryptography.Catalog.PFN_CDF_PARSE_ERROR_CALLBACK pfnParseError, in winmdroot.Security.Cryptography.Catalog.CRYPTCATMEMBER* ppMember, winmdroot.Foundation.BOOL fContinueOnError, void* pvReserved)
{
if (pwszPrevCDFTag != null && pwszPrevCDFTag.LastIndexOf('\0') == -1) throw new ("Required null terminator missing.", "pwszPrevCDFTag");
fixed (winmdroot.Security.Cryptography.Catalog.CRYPTCATMEMBER** ppMemberLocal = &ppMember)
{
fixed (char* ppwszPrevCDFTag = pwszPrevCDFTag)
{
fixed (winmdroot.Security.Cryptography.Catalog.CRYPTCATCDF* pCDFLocal = &pCDF)
{
winmdroot.Foundation.PWSTR wstrpwszPrevCDFTag = ppwszPrevCDFTag;
winmdroot.Foundation.PWSTR __result = PInvoke.CryptCATCDFEnumMembersByCDFTagEx(pCDFLocal, wstrpwszPrevCDFTag, pfnParseError, ppMemberLocal, fContinueOnError, pvReserved);
pwszPrevCDFTag = pwszPrevCDFTag.Slice(0, wstrpwszPrevCDFTag.Length);
return __result;
}
}
}
}
The generated code has return type of PWSTR
, and the corresponding parameter pwszPrevCDFTag
has type of ref Span<char>
. I tried calling PWSTR.AsSpan()
on the return value, but seems the null terminator \0
would be missing after the conversion and caused ArgumentException
exception. Seeing Value
is being an internal member of PWSTR
, what is the recommended way of using the return value as pwszPrevCDFTag
argument in this scenario?
Thanks for any advice.
Originally posted by @codgician in #1294