Merge pull request #1156 from felfert/master
[mono.git] / mcs / class / corlib / System.Resources / Win32Resources.cs
index f627fc1ad05a96e5a11129d5a9ad587a848ea86d..ad58ce8823fc9092687e547878d7a6eaffed78f3 100644 (file)
@@ -9,8 +9,32 @@
 // An incomplete set of classes for manipulating Win32 resources
 //
 
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
 using System;
 using System.Collections;
+using System.Globalization;
 using System.IO;
 using System.Text;
 
@@ -212,10 +236,8 @@ internal class Win32VersionResource : Win32Resource {
        public string[] WellKnownProperties = {
                "Comments",
                "CompanyName",
-               "FileDescription",
                "FileVersion",
                "InternalName",
-               "LegalCopyright",
                "LegalTrademarks",
                "OriginalFilename",
                "ProductName",
@@ -233,9 +255,12 @@ internal class Win32VersionResource : Win32Resource {
        int file_subtype;
        long file_date;
 
+       int file_lang;
+       int file_codepage;
+
        Hashtable properties;
 
-       public Win32VersionResource (int id, int language) : base (Win32ResourceType.RT_VERSION, id, language) {
+       public Win32VersionResource (int id, int language, bool compilercontext) : base (Win32ResourceType.RT_VERSION, id, language) {
                // Initialize non-public members to the usual values used in
                // resources
                signature = 0xfeef04bd;
@@ -247,15 +272,23 @@ internal class Win32VersionResource : Win32Resource {
                file_subtype = 0;
                file_date = 0;
 
+               file_lang = compilercontext ? 0x00 : 0x7f;
+               file_codepage = 1200;
+
                properties = new Hashtable ();
 
+               string defaultvalue = compilercontext ? string.Empty : " ";
+
                // Well known properties
                foreach (string s in WellKnownProperties)
                        // The value of properties can't be empty
-                       properties [s] = " ";
+                       properties [s] = defaultvalue;
+
+               LegalCopyright = " ";
+               FileDescription = " ";
        }
 
-       public string FileVersion {
+       public string Version {
                get {
                        return 
                                "" + (file_version >> 48) + 
@@ -265,21 +298,21 @@ internal class Win32VersionResource : Win32Resource {
                }
 
                set {
-                       int[] ver = new int [4] { 0, 0, 0, 0 };
+                       long[] ver = new long [4] { 0, 0, 0, 0 };
                        if (value != null) {
                                string[] parts = value.Split ('.');
-                               
-                               for (int i = 0; i < parts.Length; ++i) {
-                                       try {
+
+                               try {
+                                       for (int i = 0; i < parts.Length; ++i) {
                                                if (i < ver.Length)
                                                        ver [i] = Int32.Parse (parts [i]);
                                        }
-                                       catch (FormatException) {
-                                       }
+                               } catch (FormatException) {
                                }
                        }
 
                        file_version = (ver [0] << 48) | (ver [1] << 32) | (ver [2] << 16) + ver [3];
+                       properties ["FileVersion"] = Version;
                }
        }
 
@@ -350,7 +383,70 @@ internal class Win32VersionResource : Win32Resource {
                        return (string)properties ["ProductVersion"];
                }
                set {
-                       properties ["ProductVersion"] = value == String.Empty ? " " : value;
+                       if (value == null || value.Length == 0)
+                               value = " ";
+
+                       long [] ver = new long [4] { 0, 0, 0, 0 };
+
+                       string [] parts = value.Split ('.');
+
+                       try {
+                               for (int i = 0; i < parts.Length; ++i) {
+                                       if (i < ver.Length)
+                                               ver [i] = Int32.Parse (parts [i]);
+                               }
+                       } catch (FormatException) {
+                       }
+
+                       properties ["ProductVersion"] = value;
+                       product_version = (ver [0] << 48) | (ver [1] << 32) | (ver [2] << 16) + ver [3];
+               }
+       }
+
+       public virtual string InternalName {
+               get {
+                       return (string)properties ["InternalName"];
+               }
+               set {
+                       properties ["InternalName"] = value == String.Empty ? " " : value;
+               }
+       }
+
+       public virtual string FileDescription {
+               get {
+                       return (string)properties ["FileDescription"];
+               }
+               set {
+                       properties ["FileDescription"] = value == String.Empty ? " " : value;
+               }
+       }
+
+       public virtual int FileLanguage {
+               get { return file_lang; }
+               set { file_lang = value; }
+       }
+
+       public virtual string FileVersion {
+               get {
+                       return (string)properties ["FileVersion"];
+               }
+               set {
+                       if (value == null || value.Length == 0)
+                               value = " ";
+
+                       long[] ver = new long [4] { 0, 0, 0, 0 };
+                       string[] parts = value.Split ('.');
+
+                       try {
+                               for (int i = 0; i < parts.Length; ++i) {
+                                       if (i < ver.Length)
+                                               ver [i] = Int32.Parse (parts [i]);
+                               }
+                       } catch (FormatException) {
+                       }
+
+                       properties ["FileVersion"] = value;
+                       file_version = (ver [0] << 48) | (ver [1] << 32) | (ver [2] << 16) + ver [3];
                }
        }
 
@@ -373,9 +469,6 @@ internal class Win32VersionResource : Win32Resource {
        public override void WriteTo (Stream ms)
        {
                using (BinaryWriter w = new BinaryWriter (ms, Encoding.Unicode)) {
-                       short len;
-                       long pos;
-
                        //
                        // See the documentation for the VS_VERSIONINFO structure and
                        // its children on MSDN
@@ -430,8 +523,8 @@ internal class Win32VersionResource : Win32Resource {
                        if ((ms.Position % 4) != 0)
                                w.Write ((short)0);
 
-                       w.Write ((short)0x7f);
-                       w.Write ((short)1200);
+                       w.Write ((short)file_lang);
+                       w.Write ((short)file_codepage);
 
                        patch_length (w, var_pos);
 
@@ -451,7 +544,7 @@ internal class Win32VersionResource : Win32Resource {
                        w.Write ((short)0);
                        w.Write ((short)0);
                        w.Write ((short)1);
-                       w.Write ("007f04b0".ToCharArray ());
+                       w.Write (String.Format ("{0:x4}{1:x4}", file_lang, file_codepage).ToCharArray ());
 
                        emit_padding (w);
 
@@ -471,6 +564,8 @@ internal class Win32VersionResource : Win32Resource {
                                w.Write (value.ToCharArray ());
                                w.Write ((short)0);
 
+                               emit_padding (w);
+
                                patch_length (w, string_pos);
                        }
 
@@ -493,26 +588,33 @@ internal class Win32ResFileReader {
 
        int read_int16 () {
                int b1 = res_file.ReadByte ();
-               int b2 = res_file.ReadByte ();
+               if (b1 == -1)
+                       return -1;
 
-               if ((b1 == -1) || (b2 == -1))
+               int b2 = res_file.ReadByte ();
+               if (b2 == -1)
                        return -1;
-               else
-                       return b1 | (b2 << 8);
+
+               return b1 | (b2 << 8);
        }
 
        int read_int32 () {
                int w1 = read_int16 ();
+               if (w1 == -1)
+                       return -1;
                int w2 = read_int16 ();
-
-               if ((w1 == -1) || (w2 == -1))
+               if (w2 == -1)
                        return -1;
+
                return w1 | (w2 << 16);
        }
 
-       private void read_padding () {
-               while ((res_file.Position % 4) != 0)
-                       read_int16 ();
+       private bool read_padding () {
+               while ((res_file.Position % 4) != 0){
+                       if (read_int16 () == -1)
+                               return false;
+               }
+               return true;
        }
 
        NameOrId read_ordinal () {
@@ -553,32 +655,40 @@ internal class Win32ResFileReader {
 
                while (true) {
 
-                       read_padding ();
-
+                       if (!read_padding ())
+                               break;
+                       
                        int data_size = read_int32 ();
 
                        if (data_size == -1)
                                /* EOF */
                                break;
 
-                       int header_size = read_int32 ();
+                       //int header_size = 
+                       read_int32 ();
                        NameOrId type = read_ordinal ();
                        NameOrId name = read_ordinal ();
 
-                       read_padding ();
-
-                       int data_version = read_int32 ();
-                       int memory_flags = read_int16 ();
+                       if (!read_padding ())
+                               break;
+                       
+                       //int data_version = 
+                       read_int32 ();
+                       //int memory_flags =
+                       read_int16 ();
                        int language_id = read_int16 ();
-                       int version = read_int32 ();
-                       int characteristics = read_int32 ();
+                       //int version =
+                       read_int32 ();
+                       //int characteristics =
+                       read_int32 ();
 
                        if (data_size == 0)
                                /* Empty resource entry */
                                continue;
 
                        byte[] data = new byte [data_size];
-                       res_file.Read (data, 0, data_size);
+                       if (res_file.Read (data, 0, data_size) != data_size)
+                               break;
 
                        resources.Add (new Win32EncodedResource (type, name, language_id, data));
                }
@@ -592,6 +702,7 @@ internal class Win32ResFileReader {
 //
 internal class ICONDIRENTRY {
 
+#pragma warning disable 649
        public byte bWidth;
        public byte bHeight;
        public byte bColorCount;
@@ -600,7 +711,7 @@ internal class ICONDIRENTRY {
        public Int16 wBitCount;
        public Int32 dwBytesInRes;
        public Int32 dwImageOffset;
-
+#pragma warning restore 649
        public byte[] image;
 
        public override string ToString () {