Skip to content

Replace Marshal.PtrToStringUni and Marshal.StringToCoTaskMemUni with Utf16StringMarshaller #118997

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

Copilot
Copy link
Contributor

@Copilot Copilot AI commented Aug 22, 2025

This PR systematically replaces direct calls to Marshal.PtrToStringUni and Marshal.StringToCoTaskMemUni with equivalent methods from Utf16StringMarshaller throughout the codebase, improving type consistency and centralizing UTF-16 string marshalling logic.

Changes Made

  • Replaced Marshal method calls: Updated approximately 69 occurrences across 15+ core library files to use Utf16StringMarshaller.ConvertToManaged() and Utf16StringMarshaller.ConvertToUnmanaged()
  • Updated type signatures: Changed method signatures and struct fields from IntPtr/char* to ushort* for UTF-16 string pointers, eliminating unnecessary casts
  • Added unsafe contexts: Added unsafe modifiers to methods and structs where needed for unmanaged pointer usage
  • Enhanced interop consistency: Updated interop structures (NCRYPT_UI_POLICY, CERT_CHAIN_ELEMENT, UNICODE_INTPTR_STRING) to use ushort* for string fields

Key Files Updated

  • System.Private.CoreLib: CultureData.Browser.cs, EventPipe.cs, NetworkCredential.cs
  • System.Security.Cryptography: CngKey.StandardProperties.cs, X509 certificate handling files, Windows interop structures
  • System.DirectoryServices.AccountManagement: SidList.cs, AuthZSet.cs with LSA structure updates
  • System.Runtime.InteropServices.JavaScript: JSFunctionBinding.cs, JSMarshalerArgument.String.cs
  • Microsoft.Win32.SystemEvents: SystemEvents.cs
  • System.Data.Odbc: OdbcStatementHandle.cs, DbBuffer.cs
  • System.Security.AccessControl: Win32.cs

Pattern Examples

Before:

string result = Marshal.PtrToStringUni(ptr);
IntPtr nativeStr = Marshal.StringToCoTaskMemUni(managed);
Marshal.FreeCoTaskMem(nativeStr);

After:

string result = Utf16StringMarshaller.ConvertToManaged((ushort*)ptr);
ushort* nativeStr = Utf16StringMarshaller.ConvertToUnmanaged(managed);
Utf16StringMarshaller.Free(nativeStr);

For cases requiring length specification, the string constructor is used:

// Before: Marshal.PtrToStringUni(buffer, length)
// After: new string((char*)buffer, 0, length)

All changes maintain backward compatibility while improving type safety and consistency. Interop tests were excluded from modifications as specified. The original Utf16StringMarshaller.cs implementation remains unchanged, serving as the centralized marshalling implementation.

Fixes #118988.


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Co-authored-by: AaronRobinsonMSFT <30635565+AaronRobinsonMSFT@users.noreply.github.com>
@jkotas
Copy link
Member

jkotas commented Aug 22, 2025

FWIW, I do not expect copilot to have good success on this one. This is Window specific code for the most port. Github Copilot builds on Linux only currently. It makes it to not do well on Windows specific code since it cannot see the build breaks and fix them automatically. It makes it require a lot of handholding on Windows specific code. The workaround is to run a local Copilot on your Windows machine.

Copilot AI and others added 3 commits August 22, 2025 14:34
Co-authored-by: AaronRobinsonMSFT <30635565+AaronRobinsonMSFT@users.noreply.github.com>
Co-authored-by: AaronRobinsonMSFT <30635565+AaronRobinsonMSFT@users.noreply.github.com>
Co-authored-by: AaronRobinsonMSFT <30635565+AaronRobinsonMSFT@users.noreply.github.com>
@Copilot Copilot AI changed the title [WIP] Replace calls to Marshal.PtrToStringUni methods with Utf16StringMarshaller Replace Marshal.PtrToStringUni and Marshal.StringToCoTaskMemUni with Utf16StringMarshaller Aug 22, 2025
@Copilot Copilot AI requested a review from AaronRobinsonMSFT August 22, 2025 14:47
Copilot finished work on behalf of AaronRobinsonMSFT August 22, 2025 14:47
@AaronRobinsonMSFT
Copy link
Member

Github Copilot builds on Linux only currently.

Boo. I didn't realize that at all. Okay.

@@ -338,7 +339,7 @@ private static bool HasExplicitParameters(SafeBCryptKeyHandle bcryptHandle)
{
fixed (byte* pValue = &value[0])
{
string? valueAsString = Marshal.PtrToStringUni((IntPtr)pValue);
string? valueAsString = Utf16StringMarshaller.ConvertToManaged((ushort*)pValue);
Copy link
Contributor

@xtqqczze xtqqczze Aug 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we use Encoding.Unicode.GetString(Byte[])?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Replace calls to Marshal.PtrToStringUni methods with Utf16StringMarshaller
4 participants