Esempio n. 1
0
        internal static unsafe IntPtr ConvertToNative(int flags, string strManaged)
        {
            if (null == strManaged)
            {
                return(IntPtr.Zero);
            }

            byte[]? bytes = null;
            int nb = 0;

            if (strManaged.Length > 0)
            {
                bytes = AnsiCharMarshaler.DoAnsiConversion(strManaged, 0 != (flags & 0xFF), 0 != (flags >> 8), out nb);
            }

            uint   length = (uint)nb;
            IntPtr bstr   = Marshal.AllocBSTRByteLen(length);

            if (bytes != null)
            {
                Buffer.Memmove(ref *(byte *)bstr, ref MemoryMarshal.GetArrayDataReference(bytes), length);
            }

            return(bstr);
        }
Esempio n. 2
0
        internal static unsafe IntPtr ConvertToNative(string strManaged, IntPtr pNativeBuffer)
        {
            if (null == strManaged)
            {
                return(IntPtr.Zero);
            }
            else
            {
                bool hasTrailByte = strManaged.TryGetTrailByte(out byte trailByte);

                uint lengthInBytes = (uint)strManaged.Length * 2;

                if (hasTrailByte)
                {
                    // this is an odd-sized string with a trailing byte stored in its sync block
                    lengthInBytes++;
                }

                byte *ptrToFirstChar;

                if (pNativeBuffer != IntPtr.Zero)
                {
                    // If caller provided a buffer, construct the BSTR manually. The size
                    // of the buffer must be at least (lengthInBytes + 6) bytes.
#if DEBUG
                    uint length = *((uint *)pNativeBuffer);
                    Debug.Assert(length >= lengthInBytes + 6, "BSTR localloc'ed buffer is too small");
#endif

                    // set length
                    *((uint *)pNativeBuffer) = lengthInBytes;

                    ptrToFirstChar = (byte *)pNativeBuffer + 4;
                }
                else
                {
                    // If not provided, allocate the buffer using Marshal.AllocBSTRByteLen so
                    // that odd-sized strings will be handled as well.
                    ptrToFirstChar = (byte *)Marshal.AllocBSTRByteLen(lengthInBytes);
                }

                // copy characters from the managed string
                Buffer.Memmove(ref *(char *)ptrToFirstChar, ref strManaged.GetRawStringData(), (nuint)strManaged.Length + 1);

                // copy the trail byte if present
                if (hasTrailByte)
                {
                    ptrToFirstChar[lengthInBytes - 1] = trailByte;
                }

                // return ptr to first character
                return((IntPtr)ptrToFirstChar);
            }
        }
Esempio n. 3
0
        internal static unsafe byte *StringToAnsiBstrBuffer(string s)
        {
            if (s is null)
            {
                return((byte *)IntPtr.Zero);
            }

            int stringLength = s.Length;

            fixed(char *pStr = s)
            {
                int   nativeLength = PInvokeMarshal.GetByteCount(pStr, stringLength);
                byte *bstr         = (byte *)Marshal.AllocBSTRByteLen((uint)nativeLength);

                PInvokeMarshal.ConvertWideCharToMultiByte(pStr, stringLength, bstr, nativeLength, bestFit: false, throwOnUnmappableChar: false);
                return(bstr);
            }
        }
Esempio n. 4
0
            /// <summary>
            /// Initializes the marshaller with a managed string and requested buffer.
            /// </summary>
            /// <param name="managed">The managed string to initialize the marshaller with.</param>
            /// <param name="buffer">A request buffer of at least size <see cref="BufferSize"/>.</param>
            public void FromManaged(string?managed, Span <byte> buffer)
            {
                _allocated = false;

                if (managed is null)
                {
                    _ptrToFirstChar = null;
                    return;
                }

                ushort *ptrToFirstChar;
                int     lengthInBytes = checked (sizeof(char) * managed.Length);

                // A caller provided buffer must be at least (lengthInBytes + 6) bytes
                // in order to be constructed manually. The 6 extra bytes are 4 for byte length and 2 for wide null.
                int manualBstrNeeds = checked (lengthInBytes + 6);

                if (manualBstrNeeds > buffer.Length)
                {
                    // Use precise byte count when the provided stack-allocated buffer is not sufficient
                    ptrToFirstChar = (ushort *)Marshal.AllocBSTRByteLen((uint)lengthInBytes);
                    _allocated     = true;
                }
                else
                {
                    // Set length and update buffer target
                    byte *pBuffer = (byte *)Unsafe.AsPointer(ref MemoryMarshal.GetReference(buffer));
                    *((uint *)pBuffer) = (uint)lengthInBytes;
                    ptrToFirstChar     = (ushort *)(pBuffer + sizeof(uint));
                }

                // Confirm the size is properly set for the allocated BSTR.
                Debug.Assert(lengthInBytes == Marshal.SysStringByteLen((IntPtr)ptrToFirstChar));

                // Copy characters from the managed string
                managed.CopyTo(new Span <char>(ptrToFirstChar, managed.Length));
                ptrToFirstChar[managed.Length] = '\0'; // null-terminate
                _ptrToFirstChar = ptrToFirstChar;
            }