Example #1
0
 public void WriteTest()
 {
     using (var m = new SafeHGlobalHandle(10))
         using (var ms = new MarshalingStream((IntPtr)m, m.Size))
         {
             Assert.That(() => ms.Write(null, 0, 0), Throws.ArgumentNullException);
             var bytes = new byte[] { 0, 0, 0, 0, 0, 0, 0, 3 };
             Assert.That(() => ms.Write(bytes, 1, 8), Throws.ArgumentException);
             Assert.That(() => ms.Write(bytes, -1, 8), Throws.TypeOf <ArgumentOutOfRangeException>());
             Assert.That(() => ms.Write(bytes, 1, -8), Throws.TypeOf <ArgumentOutOfRangeException>());
             Assert.That(() => ms.Write(new byte[22]), Throws.TypeOf <InsufficientMemoryException>());
             ms.Write((SafeHGlobalHandle)null);
             Assert.That(ms.Position, Is.Zero);
             ms.Write((string[])null);
             Assert.That(ms.Position, Is.Zero);
             Assert.That(() => ms.Write(0L), Throws.Nothing);
         }
     using (var m = new SafeHGlobalHandle(100))
         using (var ms = new MarshalingStream((IntPtr)m, m.Size))
         {
             ms.Write(new[] { "A", "B", "C" });
             Assert.That(ms.Position, Is.GreaterThan(0));
             Assert.That(() => ms.Write(new byte[100], 0, 100), Throws.ArgumentException);
         }
 }
Example #2
0
        /// <summary>
        /// Marshals data from a managed list of strings to an unmanaged block of memory allocated by the <paramref name="memAlloc"/> method.
        /// </summary>
        /// <param name="values">The enumerated list of strings to marshal.</param>
        /// <param name="packing">The packing type for the strings.</param>
        /// <param name="memAlloc">
        /// The function that allocates the memory for the block of strings (typically <see cref="Marshal.AllocCoTaskMem(int)"/> or <see cref="Marshal.AllocHGlobal(int)"/>.
        /// </param>
        /// <param name="bytesAllocated">The bytes allocated by the <paramref name="memAlloc"/> method.</param>
        /// <param name="charSet">The character set to use for the strings.</param>
        /// <param name="prefixBytes">Number of bytes preceding the trailing strings.</param>
        /// <returns>
        /// Pointer to the allocated native (unmanaged) array of strings stored using the <paramref name="packing"/> model and the character
        /// set defined by <paramref name="charSet"/>.
        /// </returns>
        public static IntPtr MarshalToPtr(this IEnumerable <string> values, StringListPackMethod packing, Func <int, IntPtr> memAlloc, out int bytesAllocated, CharSet charSet = CharSet.Auto, int prefixBytes = 0)
        {
            // Convert to list to avoid multiple iterations
            var list = values as IList <string> ?? (values != null ? new List <string>(values) : null);

            // Look at count and bail early if 0
            var count = values?.Count() ?? 0;
            var chSz  = StringHelper.GetCharSize(charSet);

            bytesAllocated = prefixBytes + (packing == StringListPackMethod.Concatenated ? chSz : IntPtr.Size);
            if (count == 0)
            {
                var ret = memAlloc(bytesAllocated);
                Marshal.Copy(new byte[bytesAllocated], 0, ret, bytesAllocated);
                return(ret);
            }

            // Check for empty and/or null strings
            if (packing == StringListPackMethod.Concatenated && list.Any(s => string.IsNullOrEmpty(s)))
            {
                throw new ArgumentException("Concatenated string arrays cannot contain empty or null strings.");
            }

            // Get size of output
            var sumStrLen = list.Sum(s => s == null ? 0 : s.Length + 1);

            bytesAllocated += sumStrLen * chSz;
            if (packing == StringListPackMethod.Packed)
            {
                bytesAllocated += (IntPtr.Size * count);
            }

            using (var ms = new MarshalingStream(memAlloc(bytesAllocated), bytesAllocated)
            {
                Position = prefixBytes, CharSet = charSet
            })
            {
                if (packing == StringListPackMethod.Packed)
                {
                    ms.Position += (count + 1) * IntPtr.Size;
                    for (var i = 0; i < list.Count; i++)
                    {
                        ms.Poke(list[i] == null ? IntPtr.Zero : ms.Pointer.Offset(ms.Position), prefixBytes + (i * IntPtr.Size));
                        ms.Write(list[i]);
                    }
                    ms.Poke(IntPtr.Zero, prefixBytes + (count * IntPtr.Size));
                }
                else
                {
                    foreach (var s in list)
                    {
                        ms.Write(s);
                    }
                    ms.Write("");
                }

                return(ms.Pointer);
            }
        }
Example #3
0
 public void SetLengthTest()
 {
     using (var m = new SafeHGlobalHandle(1000))
         using (var ms = new MarshalingStream((IntPtr)m, m.Size))
         {
             Assert.That(() => ms.SetLength(1), Throws.Exception);
         }
 }
Example #4
0
 public void FlushTest()
 {
     using (var m = new SafeHGlobalHandle(1000))
         using (var ms = new MarshalingStream((IntPtr)m, m.Size))
         {
             ms.Flush();
         }
 }
Example #5
0
 public void PropTest()
 {
     using SafeHGlobalHandle m = new SafeHGlobalHandle(1000);
     using MarshalingStream ms = new MarshalingStream(m, m.Size);
     Assert.That(ms.Length, Is.EqualTo(1000));
     Assert.That(ms.CanWrite, Is.True);
     Assert.That(ms.CanSeek, Is.True);
     Assert.That(ms.CanRead, Is.True);
 }
Example #6
0
 public void SeekTest()
 {
     using SafeHGlobalHandle m = new SafeHGlobalHandle(1000);
     using MarshalingStream ms = new MarshalingStream(m, m.Size);
     Assert.That(ms.Seek(20, SeekOrigin.Begin), Is.EqualTo(20));
     Assert.That(ms.Seek(20, SeekOrigin.Current), Is.EqualTo(40));
     Assert.That(ms.Seek(-100, SeekOrigin.End), Is.EqualTo(900));
     Assert.That(() => ms.Seek(-1, SeekOrigin.Begin), Throws.ArgumentException);
     Assert.That(() => ms.Seek(1, SeekOrigin.End), Throws.ArgumentException);
 }
Example #7
0
 public void PropTest()
 {
     using (var m = new SafeHGlobalHandle(1000))
         using (var ms = new MarshalingStream((IntPtr)m, m.Size))
         {
             Assert.That(ms.Length, Is.EqualTo(1000));
             Assert.That(ms.CanWrite, Is.True);
             Assert.That(ms.CanSeek, Is.True);
             Assert.That(ms.CanRead, Is.True);
         }
 }
Example #8
0
 public void PokeTest()
 {
     using SafeHGlobalHandle m = new SafeHGlobalHandle(10);
     using MarshalingStream ms = new MarshalingStream(m, m.Size);
     Assert.That(() => ms.Write(0x000001FF), Throws.Nothing);
     Assert.That(ms.Position, Is.EqualTo(sizeof(int)));
     ms.Seek(0, SeekOrigin.Begin);
     byte[] ba = new byte[] { 0x2 };
     Assert.That(() => ms.Poke(null, 0), Throws.ArgumentNullException);
     Assert.That(() => ms.Poke(ba, 1000), Throws.ArgumentException);
     Assert.That(() => ms.Poke(ba, -1), Throws.TypeOf <ArgumentOutOfRangeException>());
     ms.Poke(ba, 1);
     Assert.That(ms.Read <int>(), Is.EqualTo(0x00000102));
     Assert.That(() => ms.Read <ulong>(), Throws.TypeOf <ArgumentOutOfRangeException>());
 }
 public void PokeTest()
 {
     using (var m = new SafeHGlobalHandle(10))
         using (var ms = new MarshalingStream((IntPtr)m, m.Size))
         {
             Assert.That(() => ms.Write(0x000001FF), Throws.Nothing);
             Assert.That(ms.Position, Is.EqualTo(sizeof(int)));
             ms.Seek(0, SeekOrigin.Begin);
             var ba = new byte[] { 0x2 };
             Assert.That(() => ms.Poke(null, 0), Throws.ArgumentNullException);
             Assert.That(() => ms.Poke(ba, 1000), Throws.ArgumentException);
             Assert.That(() => ms.Poke(ba, -1), Throws.TypeOf <ArgumentOutOfRangeException>());
             ms.Poke(ba, 1);
             Assert.That(ms.Read <int>(), Is.EqualTo(0x00000102));
             Assert.That(() => ms.Read <Vanara.PInvoke.User32_Gdi.ICONINFO>(), Throws.TypeOf <ArgumentOutOfRangeException>());
         }
 }
Example #10
0
 public void PokeTest1()
 {
     using SafeHGlobalHandle m = new SafeHGlobalHandle(100);
     using MarshalingStream ms = new MarshalingStream(m, m.Size);
     Assert.That(ms.Position, Is.Zero);
     Assert.That(() => ms.Write(new[] { 1L, 2L }), Throws.Nothing);
     byte[] bytes = new byte[] { 0, 0, 0, 0, 0, 0, 0, 3 };
     ms.Write(bytes, 0, bytes.Length);
     Assert.That(ms.Position, Is.EqualTo(sizeof(long) * 2 + 8));
     ms.Seek(0, SeekOrigin.Begin);
     Assert.That(() => ms.Poke(IntPtr.Zero, 1002), Throws.ArgumentException);
     Assert.That(() => ms.Poke(IntPtr.Zero, -1), Throws.TypeOf <ArgumentOutOfRangeException>());
     ms.Poke(IntPtr.Zero, sizeof(long));
     byte[] buf = new byte[24];
     ms.Read(buf, 0, buf.Length);
     Assert.That(buf, Is.EquivalentTo(new byte[] { 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3 }));
     Assert.That(() => ms.Read(null, 0, 0), Throws.ArgumentNullException);
     Assert.That(() => ms.Read(buf, 0, 30), Throws.ArgumentException);
     Assert.That(() => ms.Read(buf, -1, 0), Throws.TypeOf <ArgumentOutOfRangeException>());
     ms.Position = m.Size - 10;
     Assert.That(() => ms.Read(buf, 0, buf.Length), Throws.Nothing);
 }
Example #11
0
 public void MarshalingStreamTest()
 {
     using (var m = new SafeHGlobalHandle(1024))
         using (var ms = new MarshalingStream((IntPtr)m, m.Size))
             Assert.That(ms.Capacity, Is.EqualTo((long)m.Size));
 }
Example #12
0
 public void SetLengthTest()
 {
     using SafeHGlobalHandle m = new SafeHGlobalHandle(1000);
     using MarshalingStream ms = new MarshalingStream(m, m.Size);
     Assert.That(() => ms.SetLength(1), Throws.Exception);
 }
Example #13
0
 public void FlushTest()
 {
     using SafeHGlobalHandle m = new SafeHGlobalHandle(1000);
     using MarshalingStream ms = new MarshalingStream(m, m.Size);
     ms.Flush();
 }
Example #14
0
 public void MarshalingStreamTest()
 {
     using SafeHGlobalHandle m = new SafeHGlobalHandle(1024);
     using MarshalingStream ms = new MarshalingStream(m, m.Size);
     Assert.That(ms.Capacity, Is.EqualTo((long)m.Size));
 }
Example #15
0
        /// <summary>
        /// Marshals data from a managed list of objects to an unmanaged block of memory allocated by the <paramref name="memAlloc"/> method.
        /// </summary>
        /// <param name="values">The enumerated list of objects to marshal.</param>
        /// <param name="memAlloc">
        /// The function that allocates the memory for the block of objects (typically <see cref="Marshal.AllocCoTaskMem(int)"/> or <see cref="Marshal.AllocHGlobal(int)"/>.
        /// </param>
        /// <param name="bytesAllocated">The bytes allocated by the <paramref name="memAlloc"/> method.</param>
        /// <param name="referencePointers">
        /// if set to <see langword="true"/> the pointer will be processed by storing a reference to the value; if <see langword="false"/>,
        /// the pointer value will be directly inserted into the array of pointers.
        /// </param>
        /// <param name="charSet">The character set to use for strings.</param>
        /// <param name="prefixBytes">Number of bytes preceding the allocated objects.</param>
        /// <returns>Pointer to the allocated native (unmanaged) array of objects stored using the character set defined by <paramref name="charSet"/>.</returns>
        public static IntPtr MarshalObjectsToPtr(this IEnumerable <object> values, Func <int, IntPtr> memAlloc, out int bytesAllocated, bool referencePointers = false, CharSet charSet = CharSet.Auto, int prefixBytes = 0)
        {
            // Convert to list to avoid multiple iterations
            var list = values as IList <object> ?? (values != null ? new List <object>(values) : null);

            // Look at count and bail early if 0
            var count = values?.Count() ?? 0;

            bytesAllocated = prefixBytes + IntPtr.Size;
            if (count == 0)
            {
                var ret = memAlloc(bytesAllocated);
                ret.FillMemory(0, bytesAllocated);
                return(ret);
            }

            // Get size of output (array size + objects sizes)
            var chSz = StringHelper.GetCharSize(charSet);

            bytesAllocated += IntPtr.Size * count;
            bytesAllocated += list.Sum(GetSize);

            // Create pointer array
            var ptrs = new IntPtr[count + 1];

            using (var ms = new MarshalingStream(memAlloc(bytesAllocated), bytesAllocated)
            {
                Position = prefixBytes, CharSet = charSet
            })
            {
                ms.Position += (count + 1) * IntPtr.Size;
                for (var i = 0; i < list.Count; i++)
                {
                    if (!referencePointers && list[i] is IntPtr p)
                    {
                        ptrs[i] = p;
                    }
                    else
                    {
                        ptrs[i] = list[i] is null ? IntPtr.Zero : ms.Pointer.Offset(ms.Position);
                        ms.Write(list[i]);
                    }
                }
                ms.Position = 0;
                ms.Write(ptrs);

                return(ms.Pointer);
            }

            int GetSize(object o)
            {
                if (o is null)
                {
                    return(0);
                }
                if (o is string s)
                {
                    return((s.Length + 1) * chSz);
                }
                if (o is IntPtr)
                {
                    return(referencePointers ? IntPtr.Size : 0);
                }
                return(Marshal.SizeOf(o));
            }
        }