public void PersistentVarFileInfo()
        {
            // Prepare mock data.
            var versionInfo = new VersionInfoResource();

            var varFileInfo = new VarFileInfo();
            var table       = new VarTable();

            for (ushort i = 0; i < 10; i++)
            {
                table.Values.Add(i);
            }
            varFileInfo.Tables.Add(table);

            versionInfo.AddEntry(varFileInfo);

            // Serialize.
            var tempStream = new MemoryStream();

            versionInfo.Write(new BinaryStreamWriter(tempStream));

            // Reload.
            var newVersionInfo = VersionInfoResource.FromReader(new ByteArrayReader(tempStream.ToArray()));

            // Verify.
            var newVarFileInfo = newVersionInfo.GetChild <VarFileInfo>(VarFileInfo.VarFileInfoKey);

            Assert.NotNull(newVarFileInfo);
            Assert.Single(newVarFileInfo.Tables);

            var newTable = newVarFileInfo.Tables[0];

            Assert.Equal(table.Values, newTable.Values);
        }
示例#2
0
        public void TestDeepCopyBytes()
        {
            string filename = Path.Combine(Environment.SystemDirectory, "atl.dll");

            Assert.IsTrue(File.Exists(filename));
            VersionResource existingVersionResource = new VersionResource();

            existingVersionResource.Language = ResourceUtil.USENGLISHLANGID;
            Console.WriteLine("Loading {0}", filename);
            existingVersionResource.LoadFrom(filename);
            DumpResource.Dump(existingVersionResource);

            VersionResource versionResource = new VersionResource();

            versionResource.FileVersion    = existingVersionResource.FileVersion;
            versionResource.ProductVersion = existingVersionResource.ProductVersion;

            StringFileInfo existingVersionResourceStringFileInfo = (StringFileInfo)existingVersionResource["StringFileInfo"];
            VarFileInfo    existingVersionResourceVarFileInfo    = (VarFileInfo)existingVersionResource["VarFileInfo"];

            // copy string resources, data only
            StringFileInfo stringFileInfo = new StringFileInfo();

            versionResource["StringFileInfo"] = stringFileInfo;
            {
                Dictionary <string, StringTable> .Enumerator enumerator = existingVersionResourceStringFileInfo.Strings.GetEnumerator();
                while (enumerator.MoveNext())
                {
                    StringTable stringTable = new StringTable(enumerator.Current.Key);
                    stringFileInfo.Strings.Add(enumerator.Current.Key, stringTable);
                    Dictionary <string, StringTableEntry> .Enumerator resourceEnumerator = enumerator.Current.Value.Strings.GetEnumerator();
                    while (resourceEnumerator.MoveNext())
                    {
                        StringTableEntry stringResource = new StringTableEntry(resourceEnumerator.Current.Key);
                        stringResource.Value = resourceEnumerator.Current.Value.Value;
                        stringTable.Strings.Add(resourceEnumerator.Current.Key, stringResource);
                    }
                }
            }

            // copy var resources, data only
            VarFileInfo varFileInfo = new VarFileInfo();

            versionResource["VarFileInfo"] = varFileInfo;
            {
                Dictionary <string, VarTable> .Enumerator enumerator = existingVersionResourceVarFileInfo.Vars.GetEnumerator();
                while (enumerator.MoveNext())
                {
                    VarTable varTable = new VarTable(enumerator.Current.Key);
                    varFileInfo.Vars.Add(enumerator.Current.Key, varTable);
                    Dictionary <UInt16, UInt16> .Enumerator translationEnumerator = enumerator.Current.Value.Languages.GetEnumerator();
                    while (translationEnumerator.MoveNext())
                    {
                        varTable.Languages.Add(translationEnumerator.Current.Key, translationEnumerator.Current.Value);
                    }
                }
            }

            ByteUtils.CompareBytes(existingVersionResource.WriteAndGetBytes(), versionResource.WriteAndGetBytes());
        }
        internal static VarFileInfo ReadVarFileInfo(this PeReader reader)
        {
            var orgPos = reader.GetPosition();

            var info = new VarFileInfo();

            if (!reader.ReadFileInfo(info, "VarFileInfo"))
            {
                return(null);
            }

            var var = new Var();

            if (!reader.ReadFileInfo(var, "Translation"))
            {
                return(null);
            }

            info.Value = var;

            var codes = new List <ulong>();

            while (reader.GetPosition() < var.Position + var.Length)
            {
                ulong code = reader.ReadUInt16();
                code = reader.ReadUInt16() | (code << 16);
                codes.Add(code);
            }

            info.Value.LanguageCodes = codes.ToImmutableArray();

            return(info);
        }
        public void TestLoadAndSaveVersionResource(string binaryName)
        {
            Uri    uri      = new Uri(Assembly.GetExecutingAssembly().CodeBase);
            string filename = Path.Combine(Path.GetDirectoryName(HttpUtility.UrlDecode(uri.AbsolutePath)), "Binaries\\" + binaryName);

            Assert.IsTrue(File.Exists(filename));

            VersionResource versionResource = new VersionResource();

            versionResource.Language = ResourceUtil.USENGLISHLANGID;
            versionResource.LoadFrom(filename);
            DumpResource.Dump(versionResource);

            versionResource.FileVersion    = "1.2.3.4";
            versionResource.ProductVersion = "5.6.7.8";
            versionResource.FileFlags      = 0x2 | 0x8; // private and prerelease

            StringFileInfo stringFileInfo = (StringFileInfo)versionResource["StringFileInfo"];

            stringFileInfo["Comments"] = string.Format("{0}\0", Guid.NewGuid());
            stringFileInfo["NewValue"] = string.Format("{0}\0", Guid.NewGuid());

            VarFileInfo varFileInfo = (VarFileInfo)versionResource["VarFileInfo"];

            varFileInfo[ResourceUtil.USENGLISHLANGID] = 1300;

            string targetFilename = Path.Combine(Path.GetTempPath(), "test.dll");

            File.Copy(filename, targetFilename, true);
            Console.WriteLine(targetFilename);
            versionResource.SaveTo(targetFilename);

            VersionResource newVersionResource = new VersionResource();

            newVersionResource.Language = ResourceUtil.USENGLISHLANGID;
            newVersionResource.LoadFrom(targetFilename);
            DumpResource.Dump(versionResource);

            AssertOneVersionResource(targetFilename);
            Assert.AreEqual(newVersionResource.FileVersion, versionResource.FileVersion);
            Assert.AreEqual(newVersionResource.ProductVersion, versionResource.ProductVersion);
            Assert.AreEqual(newVersionResource.FileFlags, versionResource.FileFlags);

            StringFileInfo testedStringFileInfo = (StringFileInfo)newVersionResource["StringFileInfo"];

            foreach (KeyValuePair <string, StringTableEntry> stringResource in testedStringFileInfo.Default.Strings)
            {
                Console.WriteLine("{0} = {1}", stringResource.Value.Key, stringResource.Value.StringValue);
                Assert.AreEqual(stringResource.Value.Value, stringFileInfo[stringResource.Key]);
            }

            VarFileInfo newVarFileInfo = (VarFileInfo)newVersionResource["VarFileInfo"];

            foreach (KeyValuePair <UInt16, UInt16> varResource in newVarFileInfo.Default.Languages)
            {
                Console.WriteLine("{0} = {1}", varResource.Key, varResource.Value);
                Assert.AreEqual(varResource.Value, varFileInfo[varResource.Key]);
            }
        }
示例#5
0
 internal VersionInfo(VersionResource versionResource, uint languageId, FixedFileInfo fixedInfo, StringFileInfo stringInfo, VarFileInfo varInfo)
 {
     resource = versionResource;
     language_id = languageId;
     fixed_file_info = fixedInfo;
     string_file_info = stringInfo;
     var_file_info = varInfo;
 }
示例#6
0
 private void ClearLengths(VarFileInfo i)
 {
     ClearHeader(i);
     foreach (var v in i.Children)
     {
         ClearHeader(v);
     }
 }
        public void TestDeleteAndSaveVersionResource(string binaryName, int language)
        {
            Uri    uri      = new Uri(Assembly.GetExecutingAssembly().CodeBase);
            string filename = Path.Combine(Path.GetDirectoryName(HttpUtility.UrlDecode(uri.AbsolutePath)), "Binaries\\" + binaryName);

            Assert.IsTrue(File.Exists(filename));
            string targetFilename = Path.Combine(Path.GetTempPath(), "testDeleteAndSaveVersionResource.dll");

            File.Copy(filename, targetFilename, true);
            Console.WriteLine(targetFilename);
            VersionResource existingVersionResource = new VersionResource();

            existingVersionResource.Language = (ushort)language;
            existingVersionResource.DeleteFrom(targetFilename);

            VersionResource versionResource = new VersionResource();

            versionResource.FileVersion    = "1.2.3.4";
            versionResource.ProductVersion = "4.5.6.7";

            StringFileInfo stringFileInfo = new StringFileInfo();

            versionResource[stringFileInfo.Key] = stringFileInfo;
            StringTable stringFileInfoStrings = new StringTable(); // "040904b0"

            stringFileInfoStrings.LanguageID = (ushort)language;
            stringFileInfoStrings.CodePage   = 1200;
            Assert.AreEqual(language, stringFileInfoStrings.LanguageID);
            Assert.AreEqual(1200, stringFileInfoStrings.CodePage);
            stringFileInfo.Strings.Add(stringFileInfoStrings.Key, stringFileInfoStrings);
            stringFileInfoStrings["ProductName"]     = "ResourceLib";
            stringFileInfoStrings["FileDescription"] = "File updated by ResourceLib\0";
            stringFileInfoStrings["CompanyName"]     = "Vestris Inc.";
            stringFileInfoStrings["LegalCopyright"]  = "All Rights Reserved\0";
            stringFileInfoStrings["EmptyValue"]      = "";
            stringFileInfoStrings["Comments"]        = string.Format("{0}\0", Guid.NewGuid());
            stringFileInfoStrings["ProductVersion"]  = string.Format("{0}\0", versionResource.ProductVersion);

            VarFileInfo varFileInfo = new VarFileInfo();

            versionResource[varFileInfo.Key] = varFileInfo;
            VarTable varFileInfoTranslation = new VarTable("Translation");

            varFileInfo.Vars.Add(varFileInfoTranslation.Key, varFileInfoTranslation);
            varFileInfoTranslation[ResourceUtil.USENGLISHLANGID] = 1300;

            versionResource.SaveTo(targetFilename);
            Console.WriteLine("Reloading {0}", targetFilename);

            VersionResource newVersionResource = new VersionResource();

            newVersionResource.LoadFrom(targetFilename);
            DumpResource.Dump(newVersionResource);

            AssertOneVersionResource(targetFilename);
            Assert.AreEqual(newVersionResource.FileVersion, versionResource.FileVersion);
            Assert.AreEqual(newVersionResource.ProductVersion, versionResource.ProductVersion);
        }
示例#8
0
        public void TestDeleteAndSaveVersionResource()
        {
            string filename = Path.Combine(Environment.SystemDirectory, "atl.dll");

            Assert.IsTrue(File.Exists(filename));
            string targetFilename = Path.Combine(Path.GetTempPath(), "testDeleteAndSaveVersionResource.dll");

            File.Copy(filename, targetFilename, true);
            Console.WriteLine(targetFilename);
            VersionResource existingVersionResource = new VersionResource();

            existingVersionResource.DeleteFrom(targetFilename);

            VersionResource versionResource = new VersionResource();

            versionResource.FileVersion    = "1.2.3.4";
            versionResource.ProductVersion = "4.5.6.7";

            StringFileInfo stringFileInfo = new StringFileInfo();

            versionResource[stringFileInfo.Key] = stringFileInfo;
            StringTable stringFileInfoStrings = new StringTable(); // "040904b0"

            stringFileInfoStrings.LanguageID = 1033;
            stringFileInfoStrings.CodePage   = 1200;
            Assert.AreEqual(1033, stringFileInfoStrings.LanguageID);
            Assert.AreEqual(1200, stringFileInfoStrings.CodePage);
            stringFileInfo.Strings.Add(stringFileInfoStrings.Key, stringFileInfoStrings);
            stringFileInfoStrings["ProductName"]     = "ResourceLib";
            stringFileInfoStrings["FileDescription"] = "File updated by ResourceLib\0";
            stringFileInfoStrings["CompanyName"]     = "Vestris Inc.";
            stringFileInfoStrings["LegalCopyright"]  = "All Rights Reserved\0";
            stringFileInfoStrings["EmptyValue"]      = "";
            stringFileInfoStrings["Comments"]        = string.Format("{0}\0", Guid.NewGuid());
            stringFileInfoStrings["ProductVersion"]  = string.Format("{0}\0", versionResource.ProductVersion);

            VarFileInfo varFileInfo = new VarFileInfo();

            versionResource[varFileInfo.Key] = varFileInfo;
            VarTable varFileInfoTranslation = new VarTable("Translation");

            varFileInfo.Vars.Add(varFileInfoTranslation.Key, varFileInfoTranslation);
            varFileInfoTranslation[ResourceUtil.USENGLISHLANGID] = 1300;

            versionResource.SaveTo(targetFilename);
            Console.WriteLine("Reloading {0}", targetFilename);

            VersionResource newVersionResource = new VersionResource();

            newVersionResource.LoadFrom(targetFilename);
            DumpResource.Dump(newVersionResource);

            Assert.AreEqual(newVersionResource.FileVersion, versionResource.FileVersion);
            Assert.AreEqual(newVersionResource.ProductVersion, versionResource.ProductVersion);
        }
示例#9
0
            public VarFileInfo(BinaryReader reader)
            {
                VarFileInfo hdr = new VarFileInfo();

                this = hdr;

                byte[] buffer = new byte[Marshal.SizeOf(this)];
                reader.Read(buffer, 0, buffer.Length);
                hdr = buffer.ToStructure <VarFileInfo>();

                this = hdr;
            }
示例#10
0
        // -----------------------------------------------------
        void ReplaceVersionInfo(Options options)
        {
            // Find version info resources
            ResourceInfo ri = new ResourceInfo();

            ri.Load(options.outputExeFile);
            List <Resource> resources = ri.Resources[new ResourceId(Kernel32.ResourceTypes.RT_VERSION)];

            ri.Dispose();

            // Delete old version resource(s) from file
            foreach (Resource resource in resources)
            {
                resource.DeleteFrom(options.outputExeFile);
            }

            // Create new version info resource
            VersionResource versionResource = new VersionResource();

            versionResource.FileVersion    = options.versionInfo.fileVersion;
            versionResource.ProductVersion = options.versionInfo.productVersion;

            // Set all the info / strings
            StringFileInfo stringFileInfo = new StringFileInfo();

            versionResource[stringFileInfo.Key] = stringFileInfo;
            StringTable stringFileInfoStrings = new StringTable();

            stringFileInfoStrings.LanguageID = ResourceUtil.USENGLISHLANGID;
            stringFileInfoStrings.CodePage   = 1200;
            stringFileInfo.Strings.Add(stringFileInfoStrings.Key, stringFileInfoStrings);
//          stringFileInfoStrings["ProductName"] = "not used";
            stringFileInfoStrings["FileVersion"]     = options.versionInfo.fileVersion;
            stringFileInfoStrings["FileDescription"] = options.versionInfo.productName;
            stringFileInfoStrings["LegalCopyright"]  = options.versionInfo.legalCopyright;
            stringFileInfoStrings["CompanyName"]     = options.versionInfo.companyName;
//          stringFileInfoStrings["Comments"] = "not used";
            stringFileInfoStrings["ProductVersion"] = options.versionInfo.productVersion;

            // Don't really understand what this chunk does, but leaving it in anyway
            VarFileInfo varFileInfo = new VarFileInfo();

            versionResource[varFileInfo.Key] = varFileInfo;
            VarTable varFileInfoTranslation = new VarTable("Translation");

            varFileInfo.Vars.Add(varFileInfoTranslation.Key, varFileInfoTranslation);
            varFileInfoTranslation[ResourceUtil.USENGLISHLANGID] = 1300;

            // Save to file
            versionResource.SaveTo(options.outputExeFile);
        }
示例#11
0
        public override bool Execute()
        {
            if (!Regex.IsMatch(FileVersion, @"\d+\.\d+.\d+\.\d+"))
            {
                Log.LogError("FileVersion value '{0}' is invalid - must be NNN.NNN.NNN.NNN (where N is any digit).", FileVersion);
                return(false);
            }

            if (!Regex.IsMatch(ProductVersion, @"\d+\.\d+\.\d+\.\d+"))
            {
                Log.LogError("ProductVersion value '{0}' is invalid - must be NNN.NNN.NNN.NNN (where N is any digit).", ProductVersion);
                return(false);
            }

            foreach (ITaskItem file in InputFiles)
            {
                string fileName = file.GetMetadata("FileName") + file.GetMetadata("Extension");

                VersionResource resource = new VersionResource();
                resource.FileVersion    = FileVersion;
                resource.ProductVersion = ProductVersion;
                resource.FileFlags      = 0;

                StringTable table = new StringTable();
                table.LanguageID = 0x0409;
                table.CodePage   = 0x04B0;

                table["CompanyName"]      = CompanyName;
                table["FileDescription"]  = FileDescription;
                table["FileVersion"]      = FileVersion;
                table["InternalName"]     = fileName;
                table["LegalCopyright"]   = LegalCopyright;
                table["OriginalFilename"] = fileName;
                table["ProductName"]      = ProductName;
                table["ProductVersion"]   = ProductVersion;

                StringFileInfo stringInfo = new StringFileInfo();
                stringInfo.Strings["040904B0"]       = table;
                resource.Resources["StringFileInfo"] = stringInfo;

                VarTable varTable = new VarTable("Translation");
                varTable.Languages[0x0409] = 0x04B0;
                VarFileInfo varInfo = new VarFileInfo();
                varInfo.Vars["Translation"]       = varTable;
                resource.Resources["VarFileInfo"] = varInfo;

                resource.SaveTo(file.GetMetadata("FullPath"));
            }

            return(true);
        }
示例#12
0
    private static void StampVersion(string path, Version version)
    {
        var versionResource = new VersionResource
        {
            FileVersion    = version.ToString(),
            ProductVersion = version.ToString()
        };

        var stringFileInfo = new StringFileInfo();

        versionResource[stringFileInfo.Key] = stringFileInfo;
        var stringFileInfoStrings = new StringTable
        {
            LanguageID = 1033,
            CodePage   = 1200
        };

        stringFileInfo.Strings.Add(stringFileInfoStrings.Key, stringFileInfoStrings);
        stringFileInfoStrings["CompanyName"]      = Config.Global.Version.CompanyName;
        stringFileInfoStrings["FileDescription"]  = Config.Global.Version.FileDescription;
        stringFileInfoStrings["FileVersion"]      = version.ToString();
        stringFileInfoStrings["InternalName"]     = Config.Global.Version.InternalName;
        stringFileInfoStrings["LegalCopyright"]   = Config.Global.Version.LegalCopyright;
        stringFileInfoStrings["OriginalFilename"] = Config.Global.Version.OriginalFilename;
        stringFileInfoStrings["ProductName"]      = Config.Global.Version.ProductName;
        stringFileInfoStrings["ProductVersion"]   = version.ToString();

        var varFileInfo = new VarFileInfo();

        versionResource[varFileInfo.Key] = varFileInfo;
        var varFileInfoTranslation = new VarTable("Translation");

        varFileInfo.Vars.Add(varFileInfoTranslation.Key, varFileInfoTranslation);
        varFileInfoTranslation[ResourceUtil.USENGLISHLANGID] = 1300;

        versionResource.SaveTo(path);
    }
示例#13
0
        public void TestDeleteDeepCopyAndSaveVersionResource(string binaryName)
        {
            Uri    uri      = new Uri(Assembly.GetExecutingAssembly().CodeBase);
            string filename = Path.Combine(Path.GetDirectoryName(HttpUtility.UrlDecode(uri.AbsolutePath)), "Binaries\\" + binaryName);

            Assert.IsTrue(File.Exists(filename));
            string targetFilename = Path.Combine(Path.GetTempPath(), binaryName);

            File.Copy(filename, targetFilename, true);
            Console.WriteLine(targetFilename);
            VersionResource existingVersionResource = new VersionResource();

            existingVersionResource.Language = ResourceUtil.USENGLISHLANGID;
            existingVersionResource.LoadFrom(targetFilename);
            DumpResource.Dump(existingVersionResource);
            existingVersionResource.DeleteFrom(targetFilename);

            VersionResource versionResource = new VersionResource();

            versionResource.FileVersion    = existingVersionResource.FileVersion;
            versionResource.ProductVersion = existingVersionResource.ProductVersion;

            StringFileInfo existingVersionResourceStringFileInfo = (StringFileInfo)existingVersionResource["StringFileInfo"];
            VarFileInfo    existingVersionResourceVarFileInfo    = (VarFileInfo)existingVersionResource["VarFileInfo"];

            // copy string resources, data only
            StringFileInfo stringFileInfo = new StringFileInfo();

            versionResource["StringFileInfo"] = stringFileInfo;
            {
                Dictionary <string, StringTable> .Enumerator enumerator = existingVersionResourceStringFileInfo.Strings.GetEnumerator();
                while (enumerator.MoveNext())
                {
                    StringTable stringTable = new StringTable(enumerator.Current.Key);
                    stringFileInfo.Strings.Add(enumerator.Current.Key, stringTable);
                    Dictionary <string, StringTableEntry> .Enumerator resourceEnumerator = enumerator.Current.Value.Strings.GetEnumerator();
                    while (resourceEnumerator.MoveNext())
                    {
                        StringTableEntry stringResource = new StringTableEntry(resourceEnumerator.Current.Key);
                        stringResource.Value = resourceEnumerator.Current.Value.Value;
                        stringTable.Strings.Add(resourceEnumerator.Current.Key, stringResource);
                    }
                }
            }

            // copy var resources, data only
            VarFileInfo varFileInfo = new VarFileInfo();

            versionResource["VarFileInfo"] = varFileInfo;
            {
                Dictionary <string, VarTable> .Enumerator enumerator = existingVersionResourceVarFileInfo.Vars.GetEnumerator();
                while (enumerator.MoveNext())
                {
                    VarTable varTable = new VarTable(enumerator.Current.Key);
                    varFileInfo.Vars.Add(enumerator.Current.Key, varTable);
                    Dictionary <UInt16, UInt16> .Enumerator translationEnumerator = enumerator.Current.Value.Languages.GetEnumerator();
                    while (translationEnumerator.MoveNext())
                    {
                        varTable.Languages.Add(translationEnumerator.Current.Key, translationEnumerator.Current.Value);
                    }
                }
            }

            versionResource.SaveTo(targetFilename);
            Console.WriteLine("Reloading {0}", targetFilename);

            VersionResource newVersionResource = new VersionResource();

            newVersionResource.LoadFrom(targetFilename);
            DumpResource.Dump(newVersionResource);

            AssertOneVersionResource(targetFilename);
            Assert.AreEqual(newVersionResource.FileVersion, versionResource.FileVersion);
            Assert.AreEqual(newVersionResource.ProductVersion, versionResource.ProductVersion);

            StringFileInfo testedStringFileInfo = (StringFileInfo)newVersionResource["StringFileInfo"];

            foreach (KeyValuePair <string, StringTableEntry> stringResource in testedStringFileInfo.Default.Strings)
            {
                Assert.AreEqual(stringResource.Value.Value, stringFileInfo[stringResource.Key]);
            }

            VarFileInfo newVarFileInfo = (VarFileInfo)newVersionResource["VarFileInfo"];

            foreach (KeyValuePair <UInt16, UInt16> varResource in newVarFileInfo.Default.Languages)
            {
                Assert.AreEqual(varResource.Value, varFileInfo[varResource.Key]);
            }
        }
示例#14
0
        public void TestDeepCopyBytes(string binaryName)
        {
            Uri    uri      = new Uri(Assembly.GetExecutingAssembly().CodeBase);
            string filename = Path.Combine(Path.GetDirectoryName(HttpUtility.UrlDecode(uri.AbsolutePath)), "Binaries\\" + binaryName);

            Assert.IsTrue(File.Exists(filename));
            VersionResource existingVersionResource = new VersionResource();

            existingVersionResource.Language = ResourceUtil.USENGLISHLANGID;
            Console.WriteLine("Loading {0}", filename);
            existingVersionResource.LoadFrom(filename);
            DumpResource.Dump(existingVersionResource);

            VersionResource versionResource = new VersionResource();

            versionResource.FileVersion    = existingVersionResource.FileVersion;
            versionResource.ProductVersion = existingVersionResource.ProductVersion;

            StringFileInfo existingVersionResourceStringFileInfo = (StringFileInfo)existingVersionResource["StringFileInfo"];
            VarFileInfo    existingVersionResourceVarFileInfo    = (VarFileInfo)existingVersionResource["VarFileInfo"];

            // copy string resources, data only
            StringFileInfo stringFileInfo = new StringFileInfo();

            versionResource["StringFileInfo"] = stringFileInfo;
            {
                Dictionary <string, StringTable> .Enumerator enumerator = existingVersionResourceStringFileInfo.Strings.GetEnumerator();
                while (enumerator.MoveNext())
                {
                    StringTable stringTable = new StringTable(enumerator.Current.Key);
                    stringFileInfo.Strings.Add(enumerator.Current.Key, stringTable);
                    Dictionary <string, StringTableEntry> .Enumerator resourceEnumerator = enumerator.Current.Value.Strings.GetEnumerator();
                    while (resourceEnumerator.MoveNext())
                    {
                        StringTableEntry stringResource = new StringTableEntry(resourceEnumerator.Current.Key);
                        stringResource.Value = resourceEnumerator.Current.Value.Value;
                        stringTable.Strings.Add(resourceEnumerator.Current.Key, stringResource);
                    }
                }
            }

            // copy var resources, data only
            VarFileInfo varFileInfo = new VarFileInfo();

            versionResource["VarFileInfo"] = varFileInfo;
            {
                Dictionary <string, VarTable> .Enumerator enumerator = existingVersionResourceVarFileInfo.Vars.GetEnumerator();
                while (enumerator.MoveNext())
                {
                    VarTable varTable = new VarTable(enumerator.Current.Key);
                    varFileInfo.Vars.Add(enumerator.Current.Key, varTable);
                    Dictionary <UInt16, UInt16> .Enumerator translationEnumerator = enumerator.Current.Value.Languages.GetEnumerator();
                    while (translationEnumerator.MoveNext())
                    {
                        varTable.Languages.Add(translationEnumerator.Current.Key, translationEnumerator.Current.Value);
                    }
                }
            }

            ByteUtils.CompareBytes(existingVersionResource.WriteAndGetBytes(), versionResource.WriteAndGetBytes());
        }
示例#15
0
        public Task<Binary> Save()
        {
            lock (this) {
                if (_saving != null) {
                    return _saving;
                }

                if (Unloaded) {
                    throw new CoAppBinaryException("Binary '{0}' has been unloaded", Filename);
                }

                if (!Modified) {
                    return this.AsResultTask();
                }

                _saving = Task<Binary>.Factory.StartNew(() => {
                    // Console.WriteLine("Actual Signing Process started for [{0}]/[{1}]", Filename , WorkingCopy);
                    if (!IsManaged) {
                        StripSignatures(WorkingCopy); // this is irrelevant if the binary is managed--we'll be writing out a new one.
                    }

                    if (!_loadOptions.HasFlag(BinaryLoadOptions.NoManaged) && IsManaged && (_modifiedManaged || _modifiedResources)) {
                        WaitForResourceAndManagedLoaders();

                        // handle managed code rewrites
                        // we can only edit the file if it's IL only, mixed mode assemblies can only be strong named, signed and native-resource-edited.
                        // set the strong name key data
                        if (!StrongNameKey.IsNullOrEmpty()) {
                            if (_mutableAssembly == null) {
                                Console.WriteLine("HEY! : {0}", Filename);
                            }

                            _mutableAssembly.PublicKey = StrongNameKey.ToList();

                            // change any assembly attributes we need to change
                            if (_mutableAssembly != null) {
                                if (StrongNameKeyCertificate != null) {
                                    foreach (var ar in _mutableAssembly.AssemblyReferences) {
                                        // rewrite assembly references that need to be updated.
                                        if (!ar.PublicKeyToken.Any()) {
                                            var dep = FindAssembly(ar.Name.Value, ar.Version.ToString());
                                            if (dep == null) {
                                                // can't strong name a file that doesn't have its deps all strong named.
                                                throw new CoAppException("dependent assembly '{0}-{1}' not available for strong naming".format(ar.Name.Value,
                                                    ar.Version.ToString()));
                                            }

                                            if (dep._mutableAssembly.PublicKey.IsNullOrEmpty()) {
                                                if (!_loadOptions.HasFlag(BinaryLoadOptions.NoUnsignedManagedDependencies)) {
                                                    Console.WriteLine(
                                                        "Warning: Non-strong-named dependent reference found: '{0}-{1}' updating with same strong-name-key.",
                                                        ar.Name, ar.Version);
                                                    dep.StrongNameKeyCertificate = StrongNameKeyCertificate;
                                                    dep.SigningCertificate = SigningCertificate;

                                                    dep.AssemblyCopyright = AssemblyCopyright;
                                                    dep.AssemblyCompany = AssemblyCompany;
                                                    dep.AssemblyProduct = AssemblyProduct;

                                                    // wait for the dependency to finish saving.
                                                    dep.Save().Wait();
                                                } else {
                                                    throw new CoAppException("dependent assembly '{0}-{1}' not strong named".format(ar.Name.Value,
                                                        ar.Version.ToString()));
                                                }
                                            }
                                            (ar as Microsoft.Cci.MutableCodeModel.AssemblyReference).PublicKeyToken =
                                                dep._mutableAssembly.PublicKeyToken.ToList();
                                            (ar as Microsoft.Cci.MutableCodeModel.AssemblyReference).PublicKey = dep._mutableAssembly.PublicKey;
                                        }
                                    }
                                }
                            }
                            // we should see if we can get assembly attributes, since sometimes they can be set, but not the native ones.
                            try {
                                if (!_mutableAssembly.AssemblyAttributes.IsNullOrEmpty()) {
                                    foreach (var a in _mutableAssembly.AssemblyAttributes) {
                                        var attributeArgument = (a.Arguments.FirstOrDefault() as MetadataConstant);
                                        if (attributeArgument != null) {
                                            var attributeName = a.Type.ToString();
                                            switch (attributeName) {
                                                case "System.Reflection.AssemblyTitleAttribute":
                                                    attributeArgument.Value = string.IsNullOrEmpty(AssemblyTitle) ? string.Empty : AssemblyTitle;
                                                    break;
                                                case "System.Reflection.AssemblyDescriptionAttribute":
                                                    attributeArgument.Value = string.IsNullOrEmpty(AssemblyDescription) ? string.Empty : AssemblyDescription;
                                                    break;
                                                case "System.Reflection.AssemblyCompanyAttribute":
                                                    attributeArgument.Value = string.IsNullOrEmpty(AssemblyCompany) ? string.Empty : AssemblyCompany;
                                                    break;
                                                case "System.Reflection.AssemblyProductAttribute":
                                                    attributeArgument.Value = string.IsNullOrEmpty(AssemblyProduct) ? string.Empty : AssemblyProduct;
                                                    break;
                                                    //case "System.Reflection.AssemblyVersionAttribute":
                                                    // attributeArgument.Value = (string)AssemblyVersion;
                                                    // break;
                                                case "System.Reflection.AssemblyFileVersionAttribute":
                                                    attributeArgument.Value = (string)AssemblyFileVersion;
                                                    break;
                                                case "System.Reflection.AssemblyCopyrightAttribute":
                                                    attributeArgument.Value = string.IsNullOrEmpty(AssemblyCopyright) ? string.Empty : AssemblyCopyright;
                                                    break;
                                                case "System.Reflection.AssemblyTrademarkAttribute":
                                                    attributeArgument.Value = string.IsNullOrEmpty(AssemblyTrademark) ? string.Empty : AssemblyTrademark;
                                                    break;
                                                case "BugTrackerAttribute":
                                                    attributeArgument.Value = string.IsNullOrEmpty(BugTracker) ? string.Empty : BugTracker;
                                                    break;
                                            }
                                        }
                                    }
                                }
                            } catch {
                                // hmm. carry on.
                            }
                        }

                        // save it to disk
                        WorkingCopy.TryHardToMakeFileWriteable();
                        using (var peStream = File.Create(WorkingCopy)) {
                            PeWriter.WritePeToStream(_mutableAssembly, _host, peStream);
                        }
                    }

                    if (!_loadOptions.HasFlag(BinaryLoadOptions.NoManifest) && Manifest.Value != null && Manifest.Value.Modified) {
                        // rewrite Manifests
                        // GS01: We only support one manifest right now.
                        // so we're gonna remove the extra ones.
                        // figure out the bigger case later.
                        var manifestKeys = NativeResources.Value.Resources.Keys.Where(each => each.ResourceType == ResourceTypes.RT_MANIFEST).ToArray();
                        foreach (var k in manifestKeys) {
                            var v = NativeResources.Value.Resources[k];
                            if (!v.IsNullOrEmpty()) {
                                foreach (var inst in v) {
                                    Resource.Delete(WorkingCopy, inst.Type, inst.Name, inst.Language);
                                }
                            }
                            NativeResources.Value.Resources.Remove(k);
                        }

                        var IsLibrary = Path.GetExtension(Filename).ToLower() == ".dll";

                        var manifestResource = new ManifestResource(IsLibrary ? ManifestType.IsolationAware : ManifestType.CreateProcess) {ManifestText = Manifest.Value.ToString(), Language = 1033};
                        // GS01: I'm hardcoding this for now. We're probably gonna have to be way smarter about this.
                        NativeResources.Value.Resources.Add(new ResourceId(ResourceTypes.RT_MANIFEST), new List<Resource> {
                            manifestResource
                        });

                        manifestResource.SaveTo(WorkingCopy);
                    }

                    if (!_loadOptions.HasFlag(BinaryLoadOptions.NoResources) && _modifiedResources) {
                        // rewrite Resources
                        VersionResource versionResource;
                        StringTable versionStringTable;

                        var versionKey = NativeResources.Value.Resources.Keys.FirstOrDefault(each => each.ResourceType == ResourceTypes.RT_VERSION);
                        if (versionKey != null) {
                            versionResource = NativeResources.Value.Resources[versionKey].First() as VersionResource;
                            versionStringTable = (versionResource["StringFileInfo"] as StringFileInfo).Strings.Values.First();
                        } else {
                            versionResource = new VersionResource();
                            NativeResources.Value.Resources.Add(new ResourceId(ResourceTypes.RT_VERSION), new List<Resource> {
                                versionResource
                            });

                            var sfi = new StringFileInfo();
                            versionResource["StringFileInfo"] = sfi;
                            sfi.Strings["040904b0"] = (versionStringTable = new StringTable("040904b0"));

                            var vfi = new VarFileInfo();
                            versionResource["VarFileInfo"] = vfi;
                            var translation = new VarTable("Translation");
                            vfi.Vars["Translation"] = translation;
                            translation[0x0409] = 0x04b0;
                        }

                        versionResource.FileVersion = FileVersion;
                        versionResource.ProductVersion = ProductVersion;

                        versionStringTable["ProductName"] = ProductName;
                        versionStringTable["CompanyName"] = CompanyName;
                        versionStringTable["FileDescription"] = FileDescription;
                        versionStringTable["Comments"] = _comments;
                        versionStringTable["Assembly Version"] = AssemblyVersion.Value;
                        versionStringTable["FileVersion"] = _fileVersion;
                        versionStringTable["ProductVersion"] = _productVersion;
                        versionStringTable["InternalName"] = _internalName;
                        versionStringTable["OriginalFilename"] = _originalFilename;
                        versionStringTable["LegalCopyright"] = _legalCopyright;
                        versionStringTable["LegalTrademarks"] = _legalTrademarks;
                        versionStringTable["BugTracker"] = _bugTracker;

                        versionResource.SaveTo(WorkingCopy);
                    }

                    if (!_loadOptions.HasFlag(BinaryLoadOptions.NoSignature) && _modifiedSignature && _signingCertificate != null) {
                        // Strongname & Sign the package

                        // strong name the binary (if we're doing managed stuff).
                        if (!_loadOptions.HasFlag(BinaryLoadOptions.NoManaged) && IsManaged && StrongNameKeyCertificate != null &&
                            (StrongNameKeyCertificate.Certificate.PrivateKey is RSACryptoServiceProvider)) {
                            ApplyStrongName(WorkingCopy, StrongNameKeyCertificate);
                        }

                        // sign the binary
                        SignFile(WorkingCopy, SigningCertificate.Certificate);
                    }

                    if (_loadingMD5 != null) {
                        _loadingMD5 = null;
                    }

                    LoadMD5().Wait();

                    // Console.WriteLine("Replacing original File [{0}]", Filename);
                    Filename.TryHardToDelete();
                    File.Copy(WorkingCopy, Filename);

                    _modified = false;
                    _modifiedResources = false;
                    _modifiedManaged = false;
                    _modifiedSignature = false;

                    // Console.WriteLine("Completed Signing Process started for [{0}]/[{1}]", Filename, WorkingCopy);
                    return this;
                });
                _saving.ContinueWith((a) => {
                    _saving = null;
                }, TaskContinuationOptions.AttachedToParent);
            }
            return _saving;
        }
示例#16
0
        public void Save(bool autoHandleDependencies = false)
        {
            lock (this) {
                if (_manifest != null)
                {
                    _pendingChanges = _manifest.Modified || _pendingChanges;
                }
                // Logger.Message("Saving Binary '{0}' : Pending Changes: {1} ", _filename, _pendingChanges);
                if (_pendingChanges)
                {
                    // saves any changes made to the binary.
                    // work on a back up of the file
                    var tmpFilename = _filename.CreateWritableWorkingCopy();

                    try {
                        // remove any digital signatures from the binary before doing anything
                        if (!IsManaged)
                        {
                            StripSignatures(tmpFilename); // this is irrelevant if the binary is managed--we'll be writing out a new one.
                        }
                        // rewrite any native resources that we want to change.

                        if (IsManaged && ILOnly)
                        {
                            // we can only edit the file if it's IL only, mixed mode assemblies can only be strong named, signed and native-resource-edited.
                            // set the strong name key data
                            MutableAssembly.PublicKey = StrongNameKey.ToList();

                            // change any assembly attributes we need to change
                            if (MutableAssembly != null)
                            {
                                if (StrongNameKeyCertificate != null)
                                {
                                    foreach (var ar in MutableAssembly.AssemblyReferences)
                                    {
                                        if (!ar.PublicKeyToken.Any())
                                        {
                                            var dep = FindAssembly(ar.Name.Value, ar.Version.ToString());
                                            if (dep == null)
                                            {
                                                // can't strong name a file that doesn't have its deps all strong named.
                                                throw new ClrPlusException("dependent assembly '{0}-{1}' not available for strong naming".format(ar.Name.Value, ar.Version.ToString()));
                                            }

                                            lock (dep) {
                                                // this should wait until the dependency is finished saving, right?
                                            }

                                            if (dep.MutableAssembly.PublicKey.IsNullOrEmpty())
                                            {
                                                if (autoHandleDependencies)
                                                {
                                                    Console.WriteLine(
                                                        "Warning: Non-strong-named dependent reference found: '{0}-{1}' updating with same strong-name-key.",
                                                        ar.Name, ar.Version);
                                                    dep.StrongNameKeyCertificate = StrongNameKeyCertificate;
                                                    dep.SigningCertificate       = SigningCertificate;

                                                    dep.AssemblyCopyright = AssemblyCopyright;
                                                    dep.AssemblyCompany   = AssemblyCompany;
                                                    dep.AssemblyProduct   = AssemblyProduct;

                                                    dep.Save();
                                                }
                                                else
                                                {
                                                    throw new ClrPlusException("dependent assembly '{0}-{1}' not strong named".format(ar.Name.Value, ar.Version.ToString()));
                                                }
                                            }
                                            (ar as Microsoft.Cci.MutableCodeModel.AssemblyReference).PublicKeyToken = dep.MutableAssembly.PublicKeyToken.ToList();
                                            (ar as Microsoft.Cci.MutableCodeModel.AssemblyReference).PublicKey      = dep.MutableAssembly.PublicKey;
                                        }
                                    }
                                }

                                // we should see if we can get assembly attributes, since sometimes they can be set, but not the native ones.
                                try {
                                    foreach (var a in MutableAssembly.AssemblyAttributes)
                                    {
                                        var attributeArgument = (a.Arguments.FirstOrDefault() as MetadataConstant);
                                        if (attributeArgument != null)
                                        {
                                            var attributeName = a.Type.ToString();
                                            switch (attributeName)
                                            {
                                            case "System.Reflection.AssemblyTitleAttribute":
                                                attributeArgument.Value = string.IsNullOrEmpty(AssemblyTitle) ? string.Empty : AssemblyTitle;
                                                break;

                                            case "System.Reflection.AssemblyDescriptionAttribute":
                                                attributeArgument.Value = string.IsNullOrEmpty(AssemblyDescription) ? string.Empty : AssemblyDescription;
                                                break;

                                            case "System.Reflection.AssemblyCompanyAttribute":
                                                attributeArgument.Value = string.IsNullOrEmpty(AssemblyCompany) ? string.Empty : AssemblyCompany;
                                                break;

                                            case "System.Reflection.AssemblyProductAttribute":
                                                attributeArgument.Value = string.IsNullOrEmpty(AssemblyProduct) ? string.Empty : AssemblyProduct;
                                                break;

                                            case "System.Reflection.AssemblyVersionAttribute":
                                                attributeArgument.Value = string.IsNullOrEmpty(AssemblyVersion) ? string.Empty : AssemblyVersion;
                                                break;

                                            case "System.Reflection.AssemblyFileVersionAttribute":
                                                attributeArgument.Value = string.IsNullOrEmpty(AssemblyFileVersion) ? string.Empty : AssemblyFileVersion;
                                                break;

                                            case "System.Reflection.AssemblyCopyrightAttribute":
                                                attributeArgument.Value = string.IsNullOrEmpty(AssemblyCopyright) ? string.Empty : AssemblyCopyright;
                                                break;

                                            case "System.Reflection.AssemblyTrademarkAttribute":
                                                attributeArgument.Value = string.IsNullOrEmpty(AssemblyTrademark) ? string.Empty : AssemblyTrademark;
                                                break;

                                            case "BugTrackerAttribute":
                                                attributeArgument.Value = string.IsNullOrEmpty(BugTracker) ? string.Empty : BugTracker;
                                                break;
                                            }
                                        }
                                    }
                                } catch {
                                    // hmm. carry on.
                                }
                            }

                            // save it to disk
                            using (var peStream = File.Create(tmpFilename)) {
                                PeWriter.WritePeToStream(MutableAssembly, _host, peStream);
                            }
                        }

                        // update native metadata
                        try {
                            var ri = new ResourceInfo();

                            ri.Load(tmpFilename);

                            if (_manifest != null && _manifest.Modified)
                            {
                                // GS01: We only support one manifest right now.
                                // so we're gonna remove the extra ones.
                                // figure out the bigger case later.
                                var manifestKeys = ri.Resources.Keys.Where(each => each.ResourceType == ResourceTypes.RT_MANIFEST).ToArray();
                                foreach (var k in manifestKeys)
                                {
                                    ri.Resources.Remove(k);
                                }

                                var manifestResource = new ManifestResource();
                                manifestResource.ManifestText = _manifest.ToString();
                                ri.Resources.Add(new ResourceId(ResourceTypes.RT_MANIFEST), new List <Resource> {
                                    manifestResource
                                });
                                manifestResource.SaveTo(tmpFilename);
                            }

                            VersionResource versionResource;
                            StringTable     versionStringTable;

                            var versionKey = ri.Resources.Keys.Where(each => each.ResourceType == ResourceTypes.RT_VERSION).FirstOrDefault();
                            if (versionKey != null)
                            {
                                versionResource    = ri.Resources[versionKey].First() as VersionResource;
                                versionStringTable = (versionResource["StringFileInfo"] as StringFileInfo).Strings.Values.First();
                            }
                            else
                            {
                                versionResource = new VersionResource();
                                ri.Resources.Add(new ResourceId(ResourceTypes.RT_VERSION), new List <Resource> {
                                    versionResource
                                });

                                var sfi = new StringFileInfo();
                                versionResource["StringFileInfo"] = sfi;
                                sfi.Strings["040904b0"]           = (versionStringTable = new StringTable("040904b0"));

                                var vfi = new VarFileInfo();
                                versionResource["VarFileInfo"] = vfi;
                                var translation = new VarTable("Translation");
                                vfi.Vars["Translation"] = translation;
                                translation[0x0409]     = 0x04b0;
                            }

                            versionResource.FileVersion    = FileVersion;
                            versionResource.ProductVersion = ProductVersion;

                            versionStringTable["ProductName"]      = ProductName;
                            versionStringTable["CompanyName"]      = CompanyName;
                            versionStringTable["FileDescription"]  = FileDescription;
                            versionStringTable["Comments"]         = _comments;
                            versionStringTable["Assembly Version"] = _assemblyVersion;
                            versionStringTable["FileVersion"]      = _fileVersion;
                            versionStringTable["ProductVersion"]   = _productVersion;
                            versionStringTable["InternalName"]     = _internalName;
                            versionStringTable["OriginalFilename"] = _originalFilename;
                            versionStringTable["LegalCopyright"]   = _legalCopyright;
                            versionStringTable["LegalTrademarks"]  = _legalTrademarks;
                            versionStringTable["BugTracker"]       = _bugTracker;

                            versionResource.SaveTo(tmpFilename);
                        } catch (Exception e) {
                            Console.WriteLine("{0} -- {1}", e.Message, e.StackTrace);
                        }

                        // strong name the binary
                        if (IsManaged && StrongNameKeyCertificate != null && (StrongNameKeyCertificate.Certificate.PrivateKey is RSACryptoServiceProvider))
                        {
                            ApplyStrongName(tmpFilename, StrongNameKeyCertificate);
                        }

                        // sign the binary
                        if (_signingCertificate != null)
                        {
                            SignFile(tmpFilename, SigningCertificate.Certificate);
                        }

                        _filename.TryHardToDelete();
                        File.Move(tmpFilename, _filename);
                    } catch (Exception e) {
#if TODO
                        Logger.Error(e);
#endif
                        // get rid of whatever we tried
                        tmpFilename.TryHardToDelete();

                        // as you were...
                        throw;
                    }
                }
                _pendingChanges = false;
                if (_manifest != null)
                {
                    _manifest.Modified = false;
                }
            }
        }
示例#17
0
        public VersionInfo GetInfo(uint languageId)
        {
            byte[] data = GetBytes(languageId);

            using (MemoryStream mem = new MemoryStream(data))
            {
                ushort len = Utils.ReadUInt16(mem);
                ushort val_len = Utils.ReadUInt16(mem);
                ushort type = Utils.ReadUInt16(mem);
                string key = Utils.ReadUnicodeString(mem);

                if (mem.Position % 4 != 0)
                    Utils.ReadUInt16(mem);

                FixedFileInfo fixed_file_info = new FixedFileInfo(mem);

                if (mem.Position % 4 != 0)
                    Utils.ReadUInt16(mem);

                StringFileInfo string_file_info = new StringFileInfo(this, mem);

                if (mem.Position % 4 != 0)
                    Utils.ReadUInt16(mem);

                VarFileInfo var_file_info = new VarFileInfo(this, mem);

                VersionInfo info = new VersionInfo(this, languageId, fixed_file_info, string_file_info, var_file_info);

                return info;
            }
        }
        public override IntPtr Read(IntPtr hModule, IntPtr lpRes)
        {
            _resources = new Dictionary<string, ResourceTable>();
            IntPtr pFixedFileInfo = _header.Read(lpRes);

            _fixedfileinfo = (Kernel32.VS_FIXEDFILEINFO)Marshal.PtrToStructure(
                pFixedFileInfo, typeof(Kernel32.VS_FIXEDFILEINFO));

            IntPtr pChild = ResourceUtil.Align(pFixedFileInfo.ToInt32() + _header.Header.wValueLength);

            while (pChild.ToInt32() < (lpRes.ToInt32() + _header.Header.wLength))
            {
                ResourceTable rc = new ResourceTable(pChild);
                switch (rc.Key)
                {
                    case "StringFileInfo":
                        rc = new StringFileInfo(pChild);
                        break;
                    default:
                        rc = new VarFileInfo(pChild);
                        break;
                }

                _resources.Add(rc.Key, rc);
                pChild = ResourceUtil.Align(pChild.ToInt32() + rc.Header.wLength);
            }

            return new IntPtr(lpRes.ToInt32() + _header.Header.wLength);
        }
示例#19
0
        public void Save(bool autoHandleDependencies = false) {
            lock (this) {
                if (_manifest != null) {
                    _pendingChanges = _manifest.Modified || _pendingChanges;
                }
                // Logger.Message("Saving Binary '{0}' : Pending Changes: {1} ", _filename, _pendingChanges);
                if (_pendingChanges) {
                    // saves any changes made to the binary.
                    // work on a back up of the file
                    var tmpFilename = _filename.CreateWritableWorkingCopy();

                    try {
                        // remove any digital signatures from the binary before doing anything
                        if (!IsManaged) {
                            StripSignatures(tmpFilename); // this is irrelevant if the binary is managed--we'll be writing out a new one.
                        }
                        // rewrite any native resources that we want to change.

                        if (IsManaged && ILOnly) {
                            // we can only edit the file if it's IL only, mixed mode assemblies can only be strong named, signed and native-resource-edited.
                            // set the strong name key data
                            MutableAssembly.PublicKey = StrongNameKey.ToList();

                            // change any assembly attributes we need to change
                            if (MutableAssembly != null) {
                                if (StrongNameKeyCertificate != null) {
                                    foreach (var ar in MutableAssembly.AssemblyReferences) {
                                        if (!ar.PublicKeyToken.Any()) {
                                            var dep = FindAssembly(ar.Name.Value, ar.Version.ToString());
                                            if (dep == null) {
                                                // can't strong name a file that doesn't have its deps all strong named.
                                                throw new ClrPlusException("dependent assembly '{0}-{1}' not available for strong naming".format(ar.Name.Value, ar.Version.ToString()));
                                            }

                                            lock (dep) {
                                                // this should wait until the dependency is finished saving, right?
                                            }

                                            if (dep.MutableAssembly.PublicKey.IsNullOrEmpty()) {
                                                if (autoHandleDependencies) {
                                                    Console.WriteLine(
                                                        "Warning: Non-strong-named dependent reference found: '{0}-{1}' updating with same strong-name-key.",
                                                        ar.Name, ar.Version);
                                                    dep.StrongNameKeyCertificate = StrongNameKeyCertificate;
                                                    dep.SigningCertificate = SigningCertificate;

                                                    dep.AssemblyCopyright = AssemblyCopyright;
                                                    dep.AssemblyCompany = AssemblyCompany;
                                                    dep.AssemblyProduct = AssemblyProduct;

                                                    dep.Save();
                                                } else {
                                                    throw new ClrPlusException("dependent assembly '{0}-{1}' not strong named".format(ar.Name.Value, ar.Version.ToString()));
                                                }
                                            }
                                            (ar as Microsoft.Cci.MutableCodeModel.AssemblyReference).PublicKeyToken = dep.MutableAssembly.PublicKeyToken.ToList();
                                            (ar as Microsoft.Cci.MutableCodeModel.AssemblyReference).PublicKey = dep.MutableAssembly.PublicKey;
                                        }
                                    }
                                }

                                // we should see if we can get assembly attributes, since sometimes they can be set, but not the native ones.
                                try {
                                    foreach (var a in MutableAssembly.AssemblyAttributes) {
                                        var attributeArgument = (a.Arguments.FirstOrDefault() as MetadataConstant);
                                        if (attributeArgument != null) {
                                            var attributeName = a.Type.ToString();
                                            switch (attributeName) {
                                                case "System.Reflection.AssemblyTitleAttribute":
                                                    attributeArgument.Value = string.IsNullOrEmpty(AssemblyTitle) ? string.Empty : AssemblyTitle;
                                                    break;
                                                case "System.Reflection.AssemblyDescriptionAttribute":
                                                    attributeArgument.Value = string.IsNullOrEmpty(AssemblyDescription) ? string.Empty : AssemblyDescription;
                                                    break;
                                                case "System.Reflection.AssemblyCompanyAttribute":
                                                    attributeArgument.Value = string.IsNullOrEmpty(AssemblyCompany) ? string.Empty : AssemblyCompany;
                                                    break;
                                                case "System.Reflection.AssemblyProductAttribute":
                                                    attributeArgument.Value = string.IsNullOrEmpty(AssemblyProduct) ? string.Empty : AssemblyProduct;
                                                    break;
                                                case "System.Reflection.AssemblyVersionAttribute":
                                                    attributeArgument.Value = string.IsNullOrEmpty(AssemblyVersion) ? string.Empty : AssemblyVersion;
                                                    break;
                                                case "System.Reflection.AssemblyFileVersionAttribute":
                                                    attributeArgument.Value = string.IsNullOrEmpty(AssemblyFileVersion) ? string.Empty : AssemblyFileVersion;
                                                    break;
                                                case "System.Reflection.AssemblyCopyrightAttribute":
                                                    attributeArgument.Value = string.IsNullOrEmpty(AssemblyCopyright) ? string.Empty : AssemblyCopyright;
                                                    break;
                                                case "System.Reflection.AssemblyTrademarkAttribute":
                                                    attributeArgument.Value = string.IsNullOrEmpty(AssemblyTrademark) ? string.Empty : AssemblyTrademark;
                                                    break;
                                                case "BugTrackerAttribute":
                                                    attributeArgument.Value = string.IsNullOrEmpty(BugTracker) ? string.Empty : BugTracker;
                                                    break;
                                            }
                                        }
                                    }
                                } catch {
                                    // hmm. carry on.
                                }
                            }

                            // save it to disk
                            using (var peStream = File.Create(tmpFilename)) {
                                PeWriter.WritePeToStream(MutableAssembly, _host, peStream);
                            }
                        }

                        // update native metadata 
                        try {
                            var ri = new ResourceInfo();

                            ri.Load(tmpFilename);

                            if (_manifest != null && _manifest.Modified) {
                                // GS01: We only support one manifest right now. 
                                // so we're gonna remove the extra ones.
                                // figure out the bigger case later. 
                                var manifestKeys = ri.Resources.Keys.Where(each => each.ResourceType == ResourceTypes.RT_MANIFEST).ToArray();
                                foreach (var k in manifestKeys) {
                                    ri.Resources.Remove(k);
                                }

                                var manifestResource = new ManifestResource();
                                manifestResource.ManifestText = _manifest.ToString();
                                ri.Resources.Add(new ResourceId(ResourceTypes.RT_MANIFEST), new List<Resource> {
                                    manifestResource
                                });
                                manifestResource.SaveTo(tmpFilename);
                            }

                            VersionResource versionResource;
                            StringTable versionStringTable;

                            var versionKey = ri.Resources.Keys.Where(each => each.ResourceType == ResourceTypes.RT_VERSION).FirstOrDefault();
                            if (versionKey != null) {
                                versionResource = ri.Resources[versionKey].First() as VersionResource;
                                versionStringTable = (versionResource["StringFileInfo"] as StringFileInfo).Strings.Values.First();
                            } else {
                                versionResource = new VersionResource();
                                ri.Resources.Add(new ResourceId(ResourceTypes.RT_VERSION), new List<Resource> {
                                    versionResource
                                });

                                var sfi = new StringFileInfo();
                                versionResource["StringFileInfo"] = sfi;
                                sfi.Strings["040904b0"] = (versionStringTable = new StringTable("040904b0"));

                                var vfi = new VarFileInfo();
                                versionResource["VarFileInfo"] = vfi;
                                var translation = new VarTable("Translation");
                                vfi.Vars["Translation"] = translation;
                                translation[0x0409] = 0x04b0;
                            }

                            versionResource.FileVersion = FileVersion;
                            versionResource.ProductVersion = ProductVersion;

                            versionStringTable["ProductName"] = ProductName;
                            versionStringTable["CompanyName"] = CompanyName;
                            versionStringTable["FileDescription"] = FileDescription;
                            versionStringTable["Comments"] = _comments;
                            versionStringTable["Assembly Version"] = _assemblyVersion;
                            versionStringTable["FileVersion"] = _fileVersion;
                            versionStringTable["ProductVersion"] = _productVersion;
                            versionStringTable["InternalName"] = _internalName;
                            versionStringTable["OriginalFilename"] = _originalFilename;
                            versionStringTable["LegalCopyright"] = _legalCopyright;
                            versionStringTable["LegalTrademarks"] = _legalTrademarks;
                            versionStringTable["BugTracker"] = _bugTracker;

                            versionResource.SaveTo(tmpFilename);
                        } catch (Exception e) {
                            Console.WriteLine("{0} -- {1}", e.Message, e.StackTrace);
                        }

                        // strong name the binary
                        if (IsManaged && StrongNameKeyCertificate != null && (StrongNameKeyCertificate.Certificate.PrivateKey is RSACryptoServiceProvider)) {
                            ApplyStrongName(tmpFilename, StrongNameKeyCertificate);
                        }

                        // sign the binary
                        if (_signingCertificate != null) {
                            SignFile(tmpFilename, SigningCertificate.Certificate);
                        }

                        _filename.TryHardToDelete();
                        File.Move(tmpFilename, _filename);
                    } catch (Exception e) {
#if TODO                        
                        Logger.Error(e);
#endif
                        // get rid of whatever we tried
                        tmpFilename.TryHardToDelete();

                        // as you were...
                        throw;
                    }
                }
                _pendingChanges = false;
                if (_manifest != null) {
                    _manifest.Modified = false;
                }
            }
        }