Exemplo n.º 1
0
        private void SaveImpl(string assemblyFileName, Stream streamOrNull, PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
        {
            ModuleBuilder manifestModule = null;

            foreach (ModuleBuilder moduleBuilder in modules)
            {
                moduleBuilder.SetIsSaved();
                moduleBuilder.PopulatePropertyAndEventTables();

                if (manifestModule == null &&
                    string.Compare(moduleBuilder.fileName, assemblyFileName, StringComparison.OrdinalIgnoreCase) == 0)
                {
                    manifestModule = moduleBuilder;
                }
            }

            if (manifestModule == null)
            {
                manifestModule = DefineDynamicModule("RefEmit_OnDiskManifestModule", assemblyFileName, false);
            }

            AssemblyTable.Record assemblyRecord = new AssemblyTable.Record();
            assemblyRecord.HashAlgId      = (int)hashAlgorithm;
            assemblyRecord.Name           = manifestModule.Strings.Add(name);
            assemblyRecord.MajorVersion   = majorVersion;
            assemblyRecord.MinorVersion   = minorVersion;
            assemblyRecord.BuildNumber    = buildVersion;
            assemblyRecord.RevisionNumber = revisionVersion;
            if (publicKey != null)
            {
                assemblyRecord.PublicKey = manifestModule.Blobs.Add(ByteBuffer.Wrap(publicKey));
                assemblyRecord.Flags     = (int)(flags | AssemblyNameFlags.PublicKey);
            }
            else
            {
                assemblyRecord.Flags = (int)(flags & ~AssemblyNameFlags.PublicKey);
            }
            if (culture != null)
            {
                assemblyRecord.Culture = manifestModule.Strings.Add(culture);
            }
            manifestModule.AssemblyTable.AddRecord(assemblyRecord);

            ResourceSection unmanagedResources = versionInfo != null || win32icon != null || win32manifest != null || win32resources != null
                ? new ResourceSection()
                : null;

            if (versionInfo != null)
            {
                versionInfo.SetName(GetName());
                versionInfo.SetFileName(assemblyFileName);
                foreach (CustomAttributeBuilder cab in customAttributes)
                {
                    // .NET doesn't support copying blob custom attributes into the version info
                    if (!cab.HasBlob || universe.DecodeVersionInfoAttributeBlobs)
                    {
                        versionInfo.SetAttribute(this, cab);
                    }
                }
                ByteBuffer versionInfoData = new ByteBuffer(512);
                versionInfo.Write(versionInfoData);
                unmanagedResources.AddVersionInfo(versionInfoData);
            }

            if (win32icon != null)
            {
                unmanagedResources.AddIcon(win32icon);
            }

            if (win32manifest != null)
            {
                unmanagedResources.AddManifest(win32manifest, fileKind == PEFileKinds.Dll ? (ushort)2 : (ushort)1);
            }

            if (win32resources != null)
            {
                unmanagedResources.ExtractResources(win32resources);
            }

            foreach (CustomAttributeBuilder cab in customAttributes)
            {
                // we intentionally don't filter out the version info (pseudo) custom attributes (to be compatible with .NET)
                manifestModule.SetCustomAttribute(0x20000001, cab);
            }

            manifestModule.AddDeclarativeSecurity(0x20000001, declarativeSecurity);

            foreach (TypeForwarder fwd in typeForwarders)
            {
                manifestModule.AddTypeForwarder(fwd.Type, fwd.IncludeNested);
            }

            foreach (ResourceFile resfile in resourceFiles)
            {
                int fileToken = AddFile(manifestModule, resfile.FileName, 1 /*ContainsNoMetaData*/);
                ManifestResourceTable.Record rec = new ManifestResourceTable.Record();
                rec.Offset         = 0;
                rec.Flags          = (int)resfile.Attributes;
                rec.Name           = manifestModule.Strings.Add(resfile.Name);
                rec.Implementation = fileToken;
                manifestModule.ManifestResource.AddRecord(rec);
            }

            int entryPointToken = 0;

            foreach (ModuleBuilder moduleBuilder in modules)
            {
                moduleBuilder.FillAssemblyRefTable();
                moduleBuilder.EmitResources();
                if (moduleBuilder != manifestModule)
                {
                    int fileToken;
                    if (entryPoint != null && entryPoint.Module == moduleBuilder)
                    {
                        ModuleWriter.WriteModule(null, null, moduleBuilder, fileKind, portableExecutableKind, imageFileMachine, moduleBuilder.unmanagedResources, entryPoint.MetadataToken);
                        entryPointToken = fileToken = AddFile(manifestModule, moduleBuilder.fileName, 0 /*ContainsMetaData*/);
                    }
                    else
                    {
                        ModuleWriter.WriteModule(null, null, moduleBuilder, fileKind, portableExecutableKind, imageFileMachine, moduleBuilder.unmanagedResources, 0);
                        fileToken = AddFile(manifestModule, moduleBuilder.fileName, 0 /*ContainsMetaData*/);
                    }
                    moduleBuilder.ExportTypes(fileToken, manifestModule);
                }
                moduleBuilder.CloseResources();
            }

            foreach (Module module in addedModules)
            {
                int fileToken = AddFile(manifestModule, module.FullyQualifiedName, 0 /*ContainsMetaData*/);
                module.ExportTypes(fileToken, manifestModule);
            }

            if (entryPointToken == 0 && entryPoint != null)
            {
                entryPointToken = entryPoint.MetadataToken;
            }

            // finally, write the manifest module
            ModuleWriter.WriteModule(keyPair, publicKey, manifestModule, fileKind, portableExecutableKind, imageFileMachine, unmanagedResources ?? manifestModule.unmanagedResources, entryPointToken, streamOrNull);
        }