Esempio n. 1
0
        public virtual long CopyTo(UnsafeNativeMethods.IStream pstm, long cb, long[] pcbRead) {

            int bufsize = 4096; // one page
            IntPtr buffer = Marshal.AllocHGlobal(bufsize);
            if (buffer == IntPtr.Zero) throw new OutOfMemoryException();
            long written = 0;
            try {
                while (written < cb) {
                    int toRead = bufsize;
                    if (written + toRead > cb) toRead  = (int) (cb - written);
                    int read = Read(buffer, toRead);
                    if (read == 0) break;
                    if (pstm.Write(buffer, read) != read) {
                        throw EFail("Wrote an incorrect number of bytes");
                    }
                    written += read;
                }
            }
            finally {
                Marshal.FreeHGlobal(buffer);
            }
            if (pcbRead != null && pcbRead.Length > 0) {
                pcbRead[0] = written;
            }

            return written;
        }
Esempio n. 2
0
 public void Dispose()
 {
     UnsafeNativeMethods.ReleaseDC(NativeMethods.NullHandleRef, new HandleRef(null, _handle));
 }
 internal static extern int GdipSaveImageToStream(HandleRef image, UnsafeNativeMethods.IStream stream, ref Guid classId, HandleRef encoderParams);
Esempio n. 4
0
        /// <include file='doc\Icon.uex' path='docs/doc[@for="Icon.Initialize"]/*' />
        /// <devdoc>
        ///     Initializes this Image object.  This is identical to calling the image's
        ///     constructor with picture, but this allows non-constructor initialization,
        ///     which may be necessary in some instances.
        /// </devdoc>
        private unsafe void Initialize(int width, int height)
        {
            if (iconData == null || handle != IntPtr.Zero)
            {
                throw new InvalidOperationException(SR.GetString(SR.IllegalState, GetType().Name));
            }

            if (iconData.Length < Marshal.SizeOf(typeof(SafeNativeMethods.ICONDIR)))
            {
                throw new ArgumentException(SR.GetString(SR.InvalidPictureType, "picture", "Icon"));
            }

            // Get the correct width / height
            //
            if (width == 0)
            {
                width = UnsafeNativeMethods.GetSystemMetrics(SafeNativeMethods.SM_CXICON);
            }

            if (height == 0)
            {
                height = UnsafeNativeMethods.GetSystemMetrics(SafeNativeMethods.SM_CYICON);
            }


            if (bitDepth == 0)
            {
                IntPtr dc = UnsafeNativeMethods.GetDC(NativeMethods.NullHandleRef);
                bitDepth  = UnsafeNativeMethods.GetDeviceCaps(new HandleRef(null, dc), SafeNativeMethods.BITSPIXEL);
                bitDepth *= UnsafeNativeMethods.GetDeviceCaps(new HandleRef(null, dc), SafeNativeMethods.PLANES);
                UnsafeNativeMethods.ReleaseDC(NativeMethods.NullHandleRef, new HandleRef(null, dc));

                // If the bitdepth is 8, make it 4.  Why?  Because windows does not
                // choose a 256 color icon if the display is running in 256 color mode
                // because of palette flicker.
                //
                if (bitDepth == 8)
                {
                    bitDepth = 4;
                }
            }

            fixed(byte *pbIconData = iconData)
            {
                SafeNativeMethods.ICONDIR *pIconDir = (SafeNativeMethods.ICONDIR *)pbIconData;

                if (pIconDir->idReserved != 0 || pIconDir->idType != 1 || pIconDir->idCount == 0)
                {
                    throw new ArgumentException(SR.GetString(SR.InvalidPictureType, "picture", "Icon"));
                }

                SafeNativeMethods.ICONDIRENTRY *pIconDirEntry = &pIconDir->idEntries;
                SafeNativeMethods.ICONDIRENTRY *pBestFit      = null;
                int bestBitDepth = 0;

                int icondirEntrySize = Marshal.SizeOf(typeof(SafeNativeMethods.ICONDIRENTRY));

                Debug.Assert((icondirEntrySize * pIconDir->idCount) < iconData.Length, "Illegal number of ICONDIRENTRIES");

                if ((icondirEntrySize * pIconDir->idCount) >= iconData.Length)
                {
                    throw new ArgumentException(SR.GetString(SR.InvalidPictureType, "picture", "Icon"));
                }

                for (int i = 0; i < pIconDir->idCount; i++)
                {
                    int iconBitDepth = pIconDirEntry->wPlanes * pIconDirEntry->wBitCount;

                    if (iconBitDepth == 0)
                    {
                        if (pIconDirEntry->bColorCount == 0)
                        {
                            iconBitDepth = 16;
                        }
                        else
                        {
                            iconBitDepth = 8;
                            if (pIconDirEntry->bColorCount < 0xFF)
                            {
                                iconBitDepth = 4;
                            }
                            if (pIconDirEntry->bColorCount < 0x10)
                            {
                                iconBitDepth = 2;
                            }
                        }
                    }

                    //  Windows rules for specifing an icon:
                    //
                    //  1.  The icon with the closest size match.
                    //  2.  For matching sizes, the image with the closest bit depth.
                    //  3.  If there is no color depth match, the icon with the closest color depth that does not exceed the display.
                    //  4.  If all icon color depth > display, lowest color depth is chosen.
                    //  5.  color depth of > 8bpp are all equal.
                    //  6.  Never choose an 8bpp icon on an 8bpp system.
                    //

                    if (pBestFit == null)
                    {
                        pBestFit     = pIconDirEntry;
                        bestBitDepth = iconBitDepth;
                    }
                    else
                    {
                        int bestDelta = Math.Abs(pBestFit->bWidth - width) + Math.Abs(pBestFit->bHeight - height);
                        int thisDelta = Math.Abs(pIconDirEntry->bWidth - width) + Math.Abs(pIconDirEntry->bHeight - height);

                        if (thisDelta < bestDelta)
                        {
                            pBestFit     = pIconDirEntry;
                            bestBitDepth = iconBitDepth;
                        }
                        else if (thisDelta == bestDelta && (iconBitDepth <= bitDepth && iconBitDepth > bestBitDepth || bestBitDepth > bitDepth && iconBitDepth < bestBitDepth))
                        {
                            pBestFit     = pIconDirEntry;
                            bestBitDepth = iconBitDepth;
                        }
                    }

                    pIconDirEntry++;
                }

                Debug.Assert(pBestFit->dwImageOffset >= 0 && (pBestFit->dwImageOffset + pBestFit->dwBytesInRes) <= iconData.Length, "Illegal offset/length for the Icon data");

                if (pBestFit->dwImageOffset < 0 || (pBestFit->dwImageOffset + pBestFit->dwBytesInRes) > iconData.Length)
                {
                    throw new ArgumentException(SR.GetString(SR.InvalidPictureType, "picture", "Icon"));
                }

                handle = SafeNativeMethods.CreateIconFromResourceEx(pbIconData + pBestFit->dwImageOffset, pBestFit->dwBytesInRes, true, 0x00030000, 0, 0, 0);
                if (handle == IntPtr.Zero)
                {
                    throw new Win32Exception();
                }
            }
        }
 internal static extern int GdipLoadImageFromStreamICM(UnsafeNativeMethods.IStream stream, out IntPtr image);
 internal static extern int GdipRecordMetafileStreamI(UnsafeNativeMethods.IStream stream, HandleRef referenceHdc, int emfType, ref GPRECT frameRect, int frameUnit, string description, out IntPtr metafile);
 internal static extern int GdipGetMetafileHeaderFromStream(UnsafeNativeMethods.IStream stream, IntPtr header);
 internal static extern int GdipCreateMetafileFromStream(UnsafeNativeMethods.IStream stream, out IntPtr metafile);
 internal static extern int GdipCreateBitmapFromStreamICM(UnsafeNativeMethods.IStream stream, out IntPtr bitmap);
Esempio n. 10
0
        // Initializes this Image object.  This is identical to calling the image's
        // constructor with picture, but this allows non-constructor initialization,
        // which may be necessary in some instances.
        private unsafe void Initialize(int width, int height)
        {
            if (_iconData == null || _handle != IntPtr.Zero)
            {
                throw new InvalidOperationException(SR.Format(SR.IllegalState, GetType().Name));
            }

            if (_iconData.Length < sizeof(SafeNativeMethods.ICONDIR))
            {
                throw new ArgumentException(SR.Format(SR.InvalidPictureType, "picture", nameof(Icon)));
            }

            // Get the correct width and height.
            if (width == 0)
            {
                width = UnsafeNativeMethods.GetSystemMetrics(SafeNativeMethods.SM_CXICON);
            }

            if (height == 0)
            {
                height = UnsafeNativeMethods.GetSystemMetrics(SafeNativeMethods.SM_CYICON);
            }

            if (s_bitDepth == 0)
            {
                IntPtr dc = Interop.User32.GetDC(IntPtr.Zero);
                s_bitDepth  = Interop.Gdi32.GetDeviceCaps(dc, Interop.Gdi32.DeviceCapability.BITSPIXEL);
                s_bitDepth *= Interop.Gdi32.GetDeviceCaps(dc, Interop.Gdi32.DeviceCapability.PLANES);
                Interop.User32.ReleaseDC(IntPtr.Zero, dc);

                // If the bitdepth is 8, make it 4 because windows does not
                // choose a 256 color icon if the display is running in 256 color mode
                // due to palette flicker.
                if (s_bitDepth == 8)
                {
                    s_bitDepth = 4;
                }
            }

            fixed(byte *b = _iconData)
            {
                SafeNativeMethods.ICONDIR *dir = (SafeNativeMethods.ICONDIR *)b;

                if (dir->idReserved != 0 || dir->idType != 1 || dir->idCount == 0)
                {
                    throw new ArgumentException(SR.Format(SR.InvalidPictureType, "picture", nameof(Icon)));
                }

                byte bestWidth  = 0;
                byte bestHeight = 0;

                if (sizeof(SafeNativeMethods.ICONDIRENTRY) * (dir->idCount - 1) + sizeof(SafeNativeMethods.ICONDIR)
                    > _iconData.Length)
                {
                    throw new ArgumentException(SR.Format(SR.InvalidPictureType, "picture", nameof(Icon)));
                }

                var entries = new ReadOnlySpan <SafeNativeMethods.ICONDIRENTRY>(&dir->idEntries, dir->idCount);

                foreach (SafeNativeMethods.ICONDIRENTRY entry in entries)
                {
                    bool fUpdateBestFit = false;
                    uint iconBitDepth;
                    if (entry.bColorCount != 0)
                    {
                        iconBitDepth = 4;
                        if (entry.bColorCount < 0x10)
                        {
                            iconBitDepth = 1;
                        }
                    }
                    else
                    {
                        iconBitDepth = entry.wBitCount;
                    }

                    // If it looks like if nothing is specified at this point then set the bits per pixel to 8.
                    if (iconBitDepth == 0)
                    {
                        iconBitDepth = 8;
                    }

                    //  Windows rules for specifing an icon:
                    //
                    //  1.  The icon with the closest size match.
                    //  2.  For matching sizes, the image with the closest bit depth.
                    //  3.  If there is no color depth match, the icon with the closest color depth that does not exceed the display.
                    //  4.  If all icon color depth > display, lowest color depth is chosen.
                    //  5.  color depth of > 8bpp are all equal.
                    //  6.  Never choose an 8bpp icon on an 8bpp system.

                    if (_bestBytesInRes == 0)
                    {
                        fUpdateBestFit = true;
                    }
                    else
                    {
                        int bestDelta = Math.Abs(bestWidth - width) + Math.Abs(bestHeight - height);
                        int thisDelta = Math.Abs(entry.bWidth - width) + Math.Abs(entry.bHeight - height);

                        if ((thisDelta < bestDelta) ||
                            (thisDelta == bestDelta && (iconBitDepth <= s_bitDepth && iconBitDepth > _bestBitDepth || _bestBitDepth > s_bitDepth && iconBitDepth < _bestBitDepth)))
                        {
                            fUpdateBestFit = true;
                        }
                    }

                    if (fUpdateBestFit)
                    {
                        bestWidth        = entry.bWidth;
                        bestHeight       = entry.bHeight;
                        _bestImageOffset = entry.dwImageOffset;
                        _bestBytesInRes  = entry.dwBytesInRes;
                        _bestBitDepth    = iconBitDepth;
                    }
                }

                if (_bestImageOffset > int.MaxValue)
                {
                    throw new ArgumentException(SR.Format(SR.InvalidPictureType, "picture", nameof(Icon)));
                }

                if (_bestBytesInRes > int.MaxValue)
                {
                    throw new Win32Exception(SafeNativeMethods.ERROR_INVALID_PARAMETER);
                }

                uint endOffset;

                try
                {
                    endOffset = checked (_bestImageOffset + _bestBytesInRes);
                }
                catch (OverflowException)
                {
                    throw new Win32Exception(SafeNativeMethods.ERROR_INVALID_PARAMETER);
                }

                if (endOffset > _iconData.Length)
                {
                    throw new ArgumentException(SR.Format(SR.InvalidPictureType, "picture", nameof(Icon)));
                }

                // Copy the bytes into an aligned buffer if needed.
                if ((_bestImageOffset % IntPtr.Size) != 0)
                {
                    // Beginning of icon's content is misaligned.
                    byte[] alignedBuffer = ArrayPool <byte> .Shared.Rent((int)_bestBytesInRes);

                    Array.Copy(_iconData, _bestImageOffset, alignedBuffer, 0, _bestBytesInRes);

                    fixed(byte *pbAlignedBuffer = alignedBuffer)
                    {
                        _handle = SafeNativeMethods.CreateIconFromResourceEx(pbAlignedBuffer, _bestBytesInRes, true, 0x00030000, 0, 0, 0);
                    }

                    ArrayPool <byte> .Shared.Return(alignedBuffer);
                }
                else
                {
                    try
                    {
                        _handle = SafeNativeMethods.CreateIconFromResourceEx(checked (b + _bestImageOffset), _bestBytesInRes, true, 0x00030000, 0, 0, 0);
                    }
                    catch (OverflowException)
                    {
                        throw new Win32Exception(SafeNativeMethods.ERROR_INVALID_PARAMETER);
                    }
                }

                if (_handle == IntPtr.Zero)
                {
                    throw new Win32Exception();
                }
            }
        }
Esempio n. 11
0
        /// <include file='doc\Icon.uex' path='docs/doc[@for="Icon.Initialize"]/*' />
        /// <devdoc>
        ///     Initializes this Image object.  This is identical to calling the image's
        ///     constructor with picture, but this allows non-constructor initialization,
        ///     which may be necessary in some instances.
        /// </devdoc>
        private unsafe void Initialize(int width, int height)
        {
            if (_iconData == null || _handle != IntPtr.Zero)
            {
                throw new InvalidOperationException(SR.Format(SR.IllegalState, GetType().Name));
            }

            int icondirSize = Marshal.SizeOf(typeof(SafeNativeMethods.ICONDIR));

            if (_iconData.Length < icondirSize)
            {
                throw new ArgumentException(SR.Format(SR.InvalidPictureType, "picture", "Icon"));
            }

            // Get the correct width / height
            //
            if (width == 0)
            {
                width = UnsafeNativeMethods.GetSystemMetrics(SafeNativeMethods.SM_CXICON);
            }

            if (height == 0)
            {
                height = UnsafeNativeMethods.GetSystemMetrics(SafeNativeMethods.SM_CYICON);
            }


            if (s_bitDepth == 0)
            {
                IntPtr dc = UnsafeNativeMethods.GetDC(NativeMethods.NullHandleRef);
                s_bitDepth  = UnsafeNativeMethods.GetDeviceCaps(new HandleRef(null, dc), SafeNativeMethods.BITSPIXEL);
                s_bitDepth *= UnsafeNativeMethods.GetDeviceCaps(new HandleRef(null, dc), SafeNativeMethods.PLANES);
                UnsafeNativeMethods.ReleaseDC(NativeMethods.NullHandleRef, new HandleRef(null, dc));

                // If the bitdepth is 8, make it 4.  Why?  Because windows does not
                // choose a 256 color icon if the display is running in 256 color mode
                // because of palette flicker.
                //
                if (s_bitDepth == 8)
                {
                    s_bitDepth = 4;
                }
            }

            fixed(byte *pbIconData = _iconData)
            {
                short idReserved = GetShort(pbIconData);
                short idType     = GetShort(pbIconData + 2);
                short idCount    = GetShort(pbIconData + 4);

                if (idReserved != 0 || idType != 1 || idCount == 0)
                {
                    throw new ArgumentException(SR.Format(SR.InvalidPictureType, "picture", "Icon"));
                }

                SafeNativeMethods.ICONDIRENTRY EntryTemp;

                byte bestWidth  = 0;
                byte bestHeight = 0;
                //int     bestBitDepth        = 0;

                byte *pbIconDirEntry   = unchecked (pbIconData + 6);
                int   icondirEntrySize = Marshal.SizeOf(typeof(SafeNativeMethods.ICONDIRENTRY));

                if ((icondirEntrySize * (idCount - 1) + icondirSize) > _iconData.Length)
                {
                    throw new ArgumentException(SR.Format(SR.InvalidPictureType, "picture", "Icon"));
                }


                for (int i = 0; i < idCount; i++)
                {
                    //
                    // Fill in EntryTemp
                    //
                    EntryTemp.bWidth        = pbIconDirEntry[0];
                    EntryTemp.bHeight       = pbIconDirEntry[1];
                    EntryTemp.bColorCount   = pbIconDirEntry[2];
                    EntryTemp.bReserved     = pbIconDirEntry[3];
                    EntryTemp.wPlanes       = GetShort(pbIconDirEntry + 4);
                    EntryTemp.wBitCount     = GetShort(pbIconDirEntry + 6);
                    EntryTemp.dwBytesInRes  = GetInt(pbIconDirEntry + 8);
                    EntryTemp.dwImageOffset = GetInt(pbIconDirEntry + 12);
                    //
                    //
                    //
                    bool fUpdateBestFit = false;
                    int  iconBitDepth   = 0;
                    if (EntryTemp.bColorCount != 0)
                    {
                        iconBitDepth = 4;
                        if (EntryTemp.bColorCount < 0x10)
                        {
                            iconBitDepth = 1;
                        }
                    }
                    else
                    {
                        iconBitDepth = EntryTemp.wBitCount;
                    }

                    // it looks like if nothing is specified at this point, bpp is 8...
                    if (iconBitDepth == 0)
                    {
                        iconBitDepth = 8;
                    }

                    //  Windows rules for specifing an icon:
                    //
                    //  1.  The icon with the closest size match.
                    //  2.  For matching sizes, the image with the closest bit depth.
                    //  3.  If there is no color depth match, the icon with the closest color depth that does not exceed the display.
                    //  4.  If all icon color depth > display, lowest color depth is chosen.
                    //  5.  color depth of > 8bpp are all equal.
                    //  6.  Never choose an 8bpp icon on an 8bpp system.
                    //

                    if (0 == _bestBytesInRes)
                    {
                        fUpdateBestFit = true;
                    }
                    else
                    {
                        int bestDelta = Math.Abs(bestWidth - width) + Math.Abs(bestHeight - height);
                        int thisDelta = Math.Abs(EntryTemp.bWidth - width) + Math.Abs(EntryTemp.bHeight - height);

                        if ((thisDelta < bestDelta) ||
                            (thisDelta == bestDelta && (iconBitDepth <= s_bitDepth && iconBitDepth > _bestBitDepth || _bestBitDepth > s_bitDepth && iconBitDepth < _bestBitDepth)))
                        {
                            fUpdateBestFit = true;
                        }
                    }

                    if (fUpdateBestFit)
                    {
                        bestWidth        = EntryTemp.bWidth;
                        bestHeight       = EntryTemp.bHeight;
                        _bestImageOffset = EntryTemp.dwImageOffset;
                        _bestBytesInRes  = EntryTemp.dwBytesInRes;
                        _bestBitDepth    = iconBitDepth;
                    }

                    pbIconDirEntry += icondirEntrySize;
                }

                if (_bestImageOffset < 0)
                {
                    throw new ArgumentException(SR.Format(SR.InvalidPictureType, "picture", "Icon"));
                }

                if (_bestBytesInRes < 0)
                {
                    throw new Win32Exception(SafeNativeMethods.ERROR_INVALID_PARAMETER);
                }

                int endOffset;

                try
                {
                    endOffset = checked (_bestImageOffset + _bestBytesInRes);
                }
                catch (OverflowException)
                {
                    throw new Win32Exception(SafeNativeMethods.ERROR_INVALID_PARAMETER);
                }

                if (endOffset > _iconData.Length)
                {
                    throw new ArgumentException(SR.Format(SR.InvalidPictureType, "picture", "Icon"));
                }

                // See DevDivBugs 17509. Copying bytes into an aligned buffer if needed
                if ((_bestImageOffset % IntPtr.Size) != 0)
                {
                    // Beginning of icon's content is misaligned
                    byte[] alignedBuffer = new byte[_bestBytesInRes];
                    Array.Copy(_iconData, _bestImageOffset, alignedBuffer, 0, _bestBytesInRes);

                    fixed(byte *pbAlignedBuffer = alignedBuffer)
                    {
                        _handle = SafeNativeMethods.CreateIconFromResourceEx(pbAlignedBuffer, _bestBytesInRes, true, 0x00030000, 0, 0, 0);
                    }
                }
                else
                {
                    try
                    {
                        _handle = SafeNativeMethods.CreateIconFromResourceEx(checked (pbIconData + _bestImageOffset), _bestBytesInRes, true, 0x00030000, 0, 0, 0);
                    }
                    catch (OverflowException)
                    {
                        throw new Win32Exception(SafeNativeMethods.ERROR_INVALID_PARAMETER);
                    }
                }
                if (_handle == IntPtr.Zero)
                {
                    throw new Win32Exception();
                }
            }
        }