internal static IntPtr ConvertToNative(int flags, string strManaged) { if (strManaged == null) { return(IntPtr.Zero); } int length = strManaged.Length; System.StubHelpers.StubHelpers.CheckStringLength(length); byte[] str = (byte[])null; int cbLength = 0; int num = 0; if (length > num) { str = AnsiCharMarshaler.DoAnsiConversion(strManaged, (uint)(flags & (int)byte.MaxValue) > 0U, (uint)(flags >> 8) > 0U, out cbLength); } return(Win32Native.SysAllocStringByteLen(str, (uint)cbLength)); }
internal static unsafe IntPtr ConvertToNative(int flags, string strManaged, IntPtr pNativeBuffer) { int num; if (strManaged == null) { return(IntPtr.Zero); } System.StubHelpers.StubHelpers.CheckStringLength(strManaged.Length); byte[] src = AnsiCharMarshaler.DoAnsiConversion(strManaged, 0 != (flags & 0xff), 0 != (flags >> 8), out num); byte * pDest = (byte *)pNativeBuffer; if (pDest == null) { pDest = (byte *)Marshal.AllocCoTaskMem(num + 2); } Buffer.memcpy(src, 0, pDest, 0, num); pDest[num] = 0; pDest[num + 1] = 0; return((IntPtr)pDest); }
internal static unsafe IntPtr ConvertToNative(string strManaged, bool fBestFit, bool fThrowOnUnmappableChar, ref int cch) { if (null == strManaged) { return(IntPtr.Zero); } byte *pNative; cch = strManaged.Length; // length field at negative offset + (# of characters incl. the terminator) * max ANSI char size int nbytes = checked (sizeof(uint) + ((cch + 1) * Marshal.SystemMaxDBCSCharSize)); pNative = (byte *)Marshal.AllocCoTaskMem(nbytes); int *pLength = (int *)pNative; pNative += sizeof(uint); if (0 == cch) { *pNative = 0; *pLength = 0; } else { byte[] bytes = AnsiCharMarshaler.DoAnsiConversion(strManaged, fBestFit, fThrowOnUnmappableChar, out int nbytesused); Debug.Assert(nbytesused >= 0 && nbytesused < nbytes, "Insufficient buffer allocated in VBByValStrMarshaler.ConvertToNative"); Buffer.Memmove(ref *pNative, ref MemoryMarshal.GetArrayDataReference(bytes), (nuint)nbytesused); pNative[nbytesused] = 0; *pLength = nbytesused; } return(new IntPtr(pNative)); }
internal static unsafe IntPtr ConvertToNative(int flags, string strManaged, IntPtr pNativeBuffer) { if (null == strManaged) { return(IntPtr.Zero); } int nb; byte *pbNativeBuffer = (byte *)pNativeBuffer; if (pbNativeBuffer != null || Marshal.SystemMaxDBCSCharSize == 1) { // If we are marshaling into a stack buffer or we can accurately estimate the size of the required heap // space, we will use a "1-pass" mode where we convert the string directly into the unmanaged buffer. // + 1 for the null character from the user. + 1 for the null character we put in. nb = checked ((strManaged.Length + 1) * Marshal.SystemMaxDBCSCharSize + 1); bool didAlloc = false; // Use the pre-allocated buffer (allocated by localloc IL instruction) if not NULL, // otherwise fallback to AllocCoTaskMem if (pbNativeBuffer == null) { pbNativeBuffer = (byte *)Marshal.AllocCoTaskMem(nb); didAlloc = true; } try { nb = Marshal.StringToAnsiString(strManaged, pbNativeBuffer, nb, bestFit: 0 != (flags & 0xFF), throwOnUnmappableChar: 0 != (flags >> 8)); } catch (Exception) when(didAlloc) { Marshal.FreeCoTaskMem((IntPtr)pbNativeBuffer); throw; } } else { if (strManaged.Length == 0) { nb = 0; pbNativeBuffer = (byte *)Marshal.AllocCoTaskMem(2); } else { // Otherwise we use a slower "2-pass" mode where we first marshal the string into an intermediate buffer // (managed byte array) and then allocate exactly the right amount of unmanaged memory. This is to avoid // wasting memory on systems with multibyte character sets where the buffer we end up with is often much // smaller than the upper bound for the given managed string. byte[] bytes = AnsiCharMarshaler.DoAnsiConversion(strManaged, fBestFit: 0 != (flags & 0xFF), fThrowOnUnmappableChar: 0 != (flags >> 8), out nb); // + 1 for the null character from the user. + 1 for the null character we put in. pbNativeBuffer = (byte *)Marshal.AllocCoTaskMem(nb + 2); Buffer.Memmove(ref *pbNativeBuffer, ref MemoryMarshal.GetArrayDataReference(bytes), (nuint)nb); } } pbNativeBuffer[nb] = 0x00; pbNativeBuffer[nb + 1] = 0x00; return((IntPtr)pbNativeBuffer); }