Click here to Skip to main content
15,884,298 members
Articles / Desktop Programming / Win32

File Resource Management Library (.NET)

Rate me:
Please Sign up or sign in to vote.
4.82/5 (27 votes)
16 Sep 2009CPOL14 min read 133.9K   2.6K   113  
A .NET implementation of a file resource management, with complete support for VS_VERSIONINFO version resources.
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.IO;

namespace Vestris.ResourceLib
{
    /// <summary>
    /// Resource utilities.
    /// </summary>
    public abstract class ResourceUtil
    {
        /// <summary>
        /// Align an address to a 4-byte boundary.
        /// </summary>
        /// <param name="p">Address in memory.</param>
        /// <returns>4-byte aligned pointer.</returns>
        internal static IntPtr Align(Int32 p)
        {
            return new IntPtr((p + 3) & ~3);
        }

        /// <summary>
        /// Align a pointer to a 4-byte boundary.
        /// </summary>
        /// <param name="p">Pointer to an address in memory.</param>
        /// <returns>4-byte aligned pointer.</returns>
        internal static IntPtr Align(IntPtr p)
        {
            return Align(p.ToInt32());
        }

        /// <summary>
        /// Pad data to a WORD.
        /// </summary>
        /// <param name="w">Binary stream.</param>
        /// <returns>New position within the binary stream.</returns>
        internal static long PadToWORD(BinaryWriter w)
        {
            long pos = w.BaseStream.Position;

            if (pos % 2 != 0)
            {
                long count = 2 - pos % 2;
                Pad(w, (UInt16)count);
                pos += count;
            }

            return pos;
        }

        /// <summary>
        /// Pad data to a DWORD.
        /// </summary>
        /// <param name="w">Binary stream.</param>
        /// <returns>New position within the binary stream.</returns>
        internal static long PadToDWORD(BinaryWriter w)
        {
            long pos = w.BaseStream.Position;

            if (pos % 4 != 0)
            {
                long count = 4 - pos % 4;
                Pad(w, (UInt16) count);
                pos += count;
            }

            return pos;
        }

        /// <summary>
        /// Returns the high WORD from a DWORD value.
        /// </summary>
        /// <param name="value">WORD value.</param>
        /// <returns>High WORD.</returns>
        internal static UInt16 HiWord(UInt32 value)
        {
            return (UInt16) ((value & 0xFFFF0000) >> 16);
        }

        /// <summary>
        /// Returns the high WORD from a DWORD value.
        /// </summary>
        /// <param name="value">WORD value.</param>
        /// <returns>High WORD.</returns>
        internal static UInt16 LoWord(UInt32 value)
        {
            return (UInt16) (value & 0x0000FFFF);
        }

        /// <summary>
        /// Write a value at a given position.
        /// Used to write a size of data in an earlier located header.
        /// </summary>
        /// <param name="w">Binary stream.</param>
        /// <param name="value">Value to write.</param>
        /// <param name="address">Address to write the value at.</param>
        internal static void WriteAt(BinaryWriter w, long value, long address)
        {
            long cur = w.BaseStream.Position;
            w.Seek((int) address, SeekOrigin.Begin);
            w.Write((UInt16) value);
            w.Seek((int) cur, SeekOrigin.Begin);
        }

        /// <summary>
        /// Pad bytes.
        /// </summary>
        /// <param name="w">Binary stream.</param>
        /// <param name="len">Number of bytes to write.</param>
        /// <returns>New position within the stream.</returns>
        internal static long Pad(BinaryWriter w, UInt16 len)
        {
            while (len-- > 0)
                w.Write((byte) 0);
            return w.BaseStream.Position;
        }

        /// <summary>
        /// Neutral language ID.
        /// </summary>
        public static UInt16 NEUTRALLANGID
        {
            get
            {
                return MAKELANGID(Kernel32.LANG_NEUTRAL, Kernel32.SUBLANG_NEUTRAL);
            }
        }

        /// <summary>
        /// US-English language ID.
        /// </summary>
        public static UInt16 USENGLISHLANGID
        {
            get
            {
                return ResourceUtil.MAKELANGID(Kernel32.LANG_ENGLISH, Kernel32.SUBLANG_ENGLISH_US);
            }
        }

        /// <summary>
        /// Make a language ID from a primary language ID (low-order 10 bits) and a sublanguage (high-order 6 bits).
        /// </summary>
        /// <param name="primary">Primary language ID.</param>
        /// <param name="sub">Sublanguage ID.</param>
        /// <returns>Microsoft language ID.</returns>
        public static UInt16 MAKELANGID(int primary, int sub)
        {
            return (UInt16) ((((UInt16)sub) << 10) | ((UInt16)primary));
        }

        /// <summary>
        /// Return the primary language ID from a Microsoft language ID.
        /// </summary>
        /// <param name="lcid">Microsoft language ID</param>
        /// <returns>primary language ID (low-order 10 bits)</returns>
        public static UInt16 PRIMARYLANGID(UInt16 lcid)
        {
            return (UInt16) (((UInt16)lcid) & 0x3ff);
        }

        /// <summary>
        /// Return the sublanguage ID from a Microsoft language ID.
        /// </summary>
        /// <param name="lcid">Microsoft language ID.</param>
        /// <returns>Sublanguage ID (high-order 6 bits).</returns>
        public static UInt16 SUBLANGID(UInt16 lcid)
        {
            return (UInt16) (((UInt16)lcid) >> 10);
        }

        /// <summary>
        /// Returns the memory representation of an object.
        /// </summary>
        /// <typeparam name="T">Object type.</typeparam>
        /// <param name="anything">Data.</param>
        /// <returns>Object's representation in memory.</returns>
        internal static byte[] GetBytes<T>(T anything)
        {
            int rawsize = Marshal.SizeOf(anything);
            IntPtr buffer = Marshal.AllocHGlobal(rawsize);
            Marshal.StructureToPtr(anything, buffer, false);
            byte[] rawdatas = new byte[rawsize];
            Marshal.Copy(buffer, rawdatas, 0, rawsize);
            Marshal.FreeHGlobal(buffer);
            return rawdatas;
        }

        /// <summary>
        /// Get a collection of flags from a flag value.
        /// </summary>
        /// <typeparam name="T">Flag collection type.</typeparam>
        /// <param name="flagValue">Flag value.</param>
        /// <returns>Collection of flags.</returns>
        internal static List<string> FlagsToList<T>(UInt32 flagValue)
        {
            List<string> flags = new List<string>();

            foreach (T f in Enum.GetValues(typeof(T)))
            {
                UInt32 f_ui = Convert.ToUInt32(f);
                if ((flagValue & f_ui) > 0 || flagValue == f_ui)
                {
                    flags.Add(f.ToString());
                }
            }

            return flags;
        }

        /// <summary>
        /// Get a string representation of flags.
        /// </summary>
        /// <typeparam name="T">Flag collection type.</typeparam>
        /// <param name="flagValue">Flag vlaue</param>
        /// <returns>String representation of flags in the f1 | ... | fn format.</returns>
        internal static string FlagsToString<T>(UInt32 flagValue)
        {
            List<string> flags = new List<string>();
            flags.AddRange(FlagsToList<T>(flagValue));
            return String.Join(" | ", flags.ToArray());
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
dB.
Team Leader Application Security Inc., www.appsecinc.com
United States United States
Daniel Doubrovkine has been in software engineering for twelve years and is currently development manager at Application Security Inc. in New York City. He has been involved in many software ventures, including Xo3 and Vestris Inc, was a development lead at Microsoft Corp. in Redmond, and director of Engineering at Visible Path Corp. in New York City. Daniel also builds and runs a foodie website, http://www.foodcandy.com.

Comments and Discussions