Exemple #1
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();
                }
            }
        }
        private unsafe void Initialize(int width, int height)
        {
            if ((this.iconData == null) || (this.handle != IntPtr.Zero))
            {
                throw new InvalidOperationException(System.Drawing.SR.GetString("IllegalState", new object[] { base.GetType().Name }));
            }
            if (this.iconData.Length < Marshal.SizeOf(typeof(SafeNativeMethods.ICONDIR)))
            {
                throw new ArgumentException(System.Drawing.SR.GetString("InvalidPictureType", new object[] { "picture", "Icon" }));
            }
            if (width == 0)
            {
                width = System.Drawing.UnsafeNativeMethods.GetSystemMetrics(11);
            }
            if (height == 0)
            {
                height = System.Drawing.UnsafeNativeMethods.GetSystemMetrics(12);
            }
            if (bitDepth == 0)
            {
                IntPtr dC = System.Drawing.UnsafeNativeMethods.GetDC(System.Drawing.NativeMethods.NullHandleRef);
                bitDepth  = System.Drawing.UnsafeNativeMethods.GetDeviceCaps(new HandleRef(null, dC), 12);
                bitDepth *= System.Drawing.UnsafeNativeMethods.GetDeviceCaps(new HandleRef(null, dC), 14);
                System.Drawing.UnsafeNativeMethods.ReleaseDC(System.Drawing.NativeMethods.NullHandleRef, new HandleRef(null, dC));
                if (bitDepth == 8)
                {
                    bitDepth = 4;
                }
            }

            fixed(byte *numRef = this.iconData)
            {
                short @short = this.GetShort(numRef);
                short num2   = this.GetShort(numRef + 2);
                short num3   = this.GetShort(numRef + 4);

                if (((@short != 0) || (num2 != 1)) || (num3 == 0))
                {
                    throw new ArgumentException(System.Drawing.SR.GetString("InvalidPictureType", new object[] { "picture", "Icon" }));
                }
                byte  bWidth  = 0;
                byte  bHeight = 0;
                int   length  = 0;
                byte *numPtr  = numRef + 6;
                int   num7    = Marshal.SizeOf(typeof(SafeNativeMethods.ICONDIRENTRY));

                if ((num7 * num3) >= this.iconData.Length)
                {
                    throw new ArgumentException(System.Drawing.SR.GetString("InvalidPictureType", new object[] { "picture", "Icon" }));
                }
                for (int i = 0; i < num3; i++)
                {
                    SafeNativeMethods.ICONDIRENTRY icondirentry;
                    icondirentry.bWidth        = numPtr[0];
                    icondirentry.bHeight       = numPtr[1];
                    icondirentry.bColorCount   = numPtr[2];
                    icondirentry.bReserved     = numPtr[3];
                    icondirentry.wPlanes       = this.GetShort(numPtr + 4);
                    icondirentry.wBitCount     = this.GetShort(numPtr + 6);
                    icondirentry.dwBytesInRes  = this.GetInt(numPtr + 8);
                    icondirentry.dwImageOffset = this.GetInt(numPtr + 12);
                    bool flag      = false;
                    int  wBitCount = 0;
                    if (icondirentry.bColorCount != 0)
                    {
                        wBitCount = 4;
                        if (icondirentry.bColorCount < 0x10)
                        {
                            wBitCount = 1;
                        }
                    }
                    else
                    {
                        wBitCount = icondirentry.wBitCount;
                    }
                    if (wBitCount == 0)
                    {
                        wBitCount = 8;
                    }
                    if (length == 0)
                    {
                        flag = true;
                    }
                    else
                    {
                        int num10        = Math.Abs((int)(bWidth - width)) + Math.Abs((int)(bHeight - height));
                        int introduced25 = Math.Abs((int)(icondirentry.bWidth - width));
                        int num11        = introduced25 + Math.Abs((int)(icondirentry.bHeight - height));
                        if ((num11 < num10) || ((num11 == num10) && (((wBitCount <= bitDepth) && (wBitCount > this.bestBitDepth)) || ((this.bestBitDepth > bitDepth) && (wBitCount < this.bestBitDepth)))))
                        {
                            flag = true;
                        }
                    }
                    if (flag)
                    {
                        bWidth  = icondirentry.bWidth;
                        bHeight = icondirentry.bHeight;
                        this.bestImageOffset = icondirentry.dwImageOffset;
                        length            = icondirentry.dwBytesInRes;
                        this.bestBitDepth = wBitCount;
                    }
                    numPtr += num7;
                }
                if ((this.bestImageOffset < 0) || ((this.bestImageOffset + length) > this.iconData.Length))
                {
                    throw new ArgumentException(System.Drawing.SR.GetString("InvalidPictureType", new object[] { "picture", "Icon" }));
                }
                if ((this.bestImageOffset % IntPtr.Size) != 0)
                {
                    byte[] destinationArray = new byte[length];
                    Array.Copy(this.iconData, this.bestImageOffset, destinationArray, 0, length);
                    fixed(byte *numRef2 = destinationArray)
                    {
                        this.handle = SafeNativeMethods.CreateIconFromResourceEx(numRef2, length, true, 0x30000, 0, 0, 0);
                    }
                }
                else
                {
                    this.handle = SafeNativeMethods.CreateIconFromResourceEx(numRef + this.bestImageOffset, length, true, 0x30000, 0, 0, 0);
                }
                if (this.handle == IntPtr.Zero)
                {
                    throw new Win32Exception();
                }
            }
        }
Exemple #3
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));

                Debug.Assert((icondirEntrySize * (idCount - 1) + icondirSize) <= _iconData.Length, "Illegal number of ICONDIRENTRIES");

                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;
                }

                Debug.Assert(_bestImageOffset >= 0 && _bestBytesInRes >= 0 && (_bestImageOffset + _bestBytesInRes) <= _iconData.Length, "Illegal offset/length for the Icon data");

                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();
                }
            }
        }
Exemple #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();
                }
            }
        }