Exemplo n.º 1
0
        internal MetadataModule(ICompilation compilation, Metadata.PEFile peFile, TypeSystemOptions options)
        {
            this.Compilation  = compilation;
            this.PEFile       = peFile;
            this.metadata     = peFile.Metadata;
            this.options      = options;
            this.TypeProvider = new TypeProvider(this);

            // assembly metadata
            if (metadata.IsAssembly)
            {
                var asmdef = metadata.GetAssemblyDefinition();
                this.AssemblyName     = metadata.GetString(asmdef.Name);
                this.FullAssemblyName = metadata.GetFullAssemblyName();
            }
            else
            {
                var moddef = metadata.GetModuleDefinition();
                this.AssemblyName     = metadata.GetString(moddef.Name);
                this.FullAssemblyName = this.AssemblyName;
            }
            this.rootNamespace = new MetadataNamespace(this, null, string.Empty, metadata.GetNamespaceDefinitionRoot());

            if (!options.HasFlag(TypeSystemOptions.Uncached))
            {
                // create arrays for resolved entities, indexed by row index
                this.typeDefs     = new MetadataTypeDefinition[metadata.TypeDefinitions.Count + 1];
                this.fieldDefs    = new MetadataField[metadata.FieldDefinitions.Count + 1];
                this.methodDefs   = new MetadataMethod[metadata.MethodDefinitions.Count + 1];
                this.propertyDefs = new MetadataProperty[metadata.PropertyDefinitions.Count + 1];
                this.eventDefs    = new MetadataEvent[metadata.EventDefinitions.Count + 1];
            }
        }
Exemplo n.º 2
0
        public static string GetPlatformName(Metadata.PEFile module)
        {
            var headers = module.Reader.PEHeaders;

            switch (headers.CoffHeader.Machine)
            {
            case Machine.I386:
                if ((headers.CorHeader.Flags & CorFlags.Prefers32Bit) != 0)
                {
                    return("AnyCPU");
                }
                else if ((headers.CorHeader.Flags & CorFlags.Requires32Bit) != 0)
                {
                    return("x86");
                }
                else
                {
                    return("AnyCPU");
                }

            case Machine.Amd64:
                return("x64");

            case Machine.IA64:
                return("Itanium");

            default:
                return(headers.CoffHeader.Machine.ToString());
            }
        }
Exemplo n.º 3
0
        internal MetadataModule(ICompilation compilation, Metadata.PEFile peFile, TypeSystemOptions options)
        {
            this.Compilation  = compilation;
            this.PEFile       = peFile;
            this.metadata     = peFile.Metadata;
            this.options      = options;
            this.TypeProvider = new TypeProvider(this);

            // assembly metadata
            if (metadata.IsAssembly)
            {
                var asmdef = metadata.GetAssemblyDefinition();
                try
                {
                    this.AssemblyName     = metadata.GetString(asmdef.Name);
                    this.AssemblyVersion  = asmdef.Version;
                    this.FullAssemblyName = metadata.GetFullAssemblyName();
                }
                catch (BadImageFormatException)
                {
                    this.AssemblyName     = "<ERR: invalid assembly name>";
                    this.FullAssemblyName = "<ERR: invalid assembly name>";
                }
            }
            else
            {
                try
                {
                    var moddef = metadata.GetModuleDefinition();
                    this.AssemblyName = metadata.GetString(moddef.Name);
                }
                catch (BadImageFormatException)
                {
                    this.AssemblyName = "<ERR: invalid assembly name>";
                }
                this.FullAssemblyName = this.AssemblyName;
            }
            var customAttrs = metadata.GetModuleDefinition().GetCustomAttributes();

            this.NullableContext        = customAttrs.GetNullableContext(metadata) ?? Nullability.Oblivious;
            this.minAccessibilityForNRT = FindMinimumAccessibilityForNRT(metadata, customAttrs);
            this.rootNamespace          = new MetadataNamespace(this, null, string.Empty, metadata.GetNamespaceDefinitionRoot());

            if (!options.HasFlag(TypeSystemOptions.Uncached))
            {
                // create arrays for resolved entities, indexed by row index
                this.typeDefs             = new MetadataTypeDefinition[metadata.TypeDefinitions.Count + 1];
                this.fieldDefs            = new MetadataField[metadata.FieldDefinitions.Count + 1];
                this.methodDefs           = new MetadataMethod[metadata.MethodDefinitions.Count + 1];
                this.propertyDefs         = new MetadataProperty[metadata.PropertyDefinitions.Count + 1];
                this.eventDefs            = new MetadataEvent[metadata.EventDefinitions.Count + 1];
                this.referencedAssemblies = new IModule[metadata.AssemblyReferences.Count + 1];
            }
        }
Exemplo n.º 4
0
        protected virtual bool IncludeTypeWhenDecompilingProject(Metadata.PEFile module, TypeDefinitionHandle type)
        {
            var metadata = module.Metadata;
            var typeDef  = metadata.GetTypeDefinition(type);

            if (metadata.GetString(typeDef.Name) == "<Module>" || CSharpDecompiler.MemberIsHidden(module, type, settings))
            {
                return(false);
            }
            if (metadata.GetString(typeDef.Namespace) == "XamlGeneratedNamespace" && metadata.GetString(typeDef.Name) == "GeneratedInternalTypeHelper")
            {
                return(false);
            }
            return(true);
        }
Exemplo n.º 5
0
        IEnumerable <Tuple <string, string> > WriteCodeFilesInProject(Metadata.PEFile module, CancellationToken cancellationToken)
        {
            var metadata = module.Metadata;
            var files    = module.Metadata.GetTopLevelTypeDefinitions().Where(td => IncludeTypeWhenDecompilingProject(module, td)).GroupBy(
                delegate(TypeDefinitionHandle h) {
                var type    = metadata.GetTypeDefinition(h);
                string file = CleanUpFileName(metadata.GetString(type.Name)) + ".cs";
                if (string.IsNullOrEmpty(metadata.GetString(type.Namespace)))
                {
                    return(file);
                }
                else
                {
                    string dir = CleanUpFileName(metadata.GetString(type.Namespace));
                    if (directories.Add(dir))
                    {
                        Directory.CreateDirectory(Path.Combine(targetDirectory, dir));
                    }
                    return(Path.Combine(dir, file));
                }
            }, StringComparer.OrdinalIgnoreCase).ToList();
            int total               = files.Count;
            var progress            = this.ProgressIndicator;
            DecompilerTypeSystem ts = new DecompilerTypeSystem(module, AssemblyResolver, settings);

            Parallel.ForEach(
                files,
                new ParallelOptions {
                MaxDegreeOfParallelism = this.MaxDegreeOfParallelism,
                CancellationToken      = cancellationToken
            },
                delegate(IGrouping <string, TypeDefinitionHandle> file) {
                using (StreamWriter w = new StreamWriter(Path.Combine(targetDirectory, file.Key))) {
                    try {
                        CSharpDecompiler decompiler  = CreateDecompiler(ts);
                        decompiler.CancellationToken = cancellationToken;
                        var syntaxTree = decompiler.DecompileTypes(file.ToArray());
                        syntaxTree.AcceptVisitor(new CSharpOutputVisitor(w, settings.CSharpFormattingOptions));
                    } catch (Exception innerException) when(!(innerException is OperationCanceledException || innerException is DecompilerException))
                    {
                        throw new DecompilerException(module, $"Error decompiling for '{file.Key}'", innerException);
                    }
                }
                progress?.Report(new DecompilationProgress(total, file.Key));
            });
            return(files.Select(f => Tuple.Create("Compile", f.Key)).Concat(WriteAssemblyInfo(ts, cancellationToken)));
        }
Exemplo n.º 6
0
        public static string GetPlatformName(Metadata.PEFile module)
        {
            var headers         = module.Reader.PEHeaders;
            var architecture    = headers.CoffHeader.Machine;
            var characteristics = headers.CoffHeader.Characteristics;
            var corflags        = headers.CorHeader.Flags;

            switch (architecture)
            {
            case Machine.I386:
                if ((corflags & CorFlags.Prefers32Bit) != 0)
                {
                    return("AnyCPU");
                }
                if ((corflags & CorFlags.Requires32Bit) != 0)
                {
                    return("x86");
                }
                // According to ECMA-335, II.25.3.3.1 CorFlags.Requires32Bit and Characteristics.Bit32Machine must be in sync
                // for assemblies containing managed code. However, this is not true for C++/CLI assemblies.
                if ((corflags & CorFlags.ILOnly) == 0 && (characteristics & Characteristics.Bit32Machine) != 0)
                {
                    return("x86");
                }
                return("AnyCPU");

            case Machine.Amd64:
                return("x64");

            case Machine.IA64:
                return("Itanium");

            default:
                return(architecture.ToString());
            }
        }
Exemplo n.º 7
0
 public static void WriteTo(this SRM.ExceptionRegion exceptionHandler, Metadata.PEFile module, GenericContext context, ITextOutput writer)
 {
     writer.Write(".try ");
     WriteOffsetReference(writer, exceptionHandler.TryOffset);
     writer.Write('-');
     WriteOffsetReference(writer, exceptionHandler.TryOffset + exceptionHandler.TryLength);
     writer.Write(' ');
     writer.Write(exceptionHandler.Kind.ToString().ToLowerInvariant());
     if (exceptionHandler.FilterOffset != -1)
     {
         writer.Write(' ');
         WriteOffsetReference(writer, exceptionHandler.FilterOffset);
         writer.Write(" handler ");
     }
     if (!exceptionHandler.CatchType.IsNil)
     {
         writer.Write(' ');
         exceptionHandler.CatchType.WriteTo(module, writer, context);
     }
     writer.Write(' ');
     WriteOffsetReference(writer, exceptionHandler.HandlerOffset);
     writer.Write('-');
     WriteOffsetReference(writer, exceptionHandler.HandlerOffset + exceptionHandler.HandlerLength);
 }
Exemplo n.º 8
0
        protected virtual IEnumerable <Tuple <string, string> > WriteResourceFilesInProject(Metadata.PEFile module)
        {
            foreach (var r in module.Resources.Where(r => r.ResourceType == Metadata.ResourceType.Embedded))
            {
                Stream stream = r.TryOpenStream();
                stream.Position = 0;

                if (r.Name.EndsWith(".resources", StringComparison.OrdinalIgnoreCase))
                {
                    bool decodedIntoIndividualFiles;
                    var  individualResources = new List <Tuple <string, string> >();
                    try {
                        var resourcesFile = new ResourcesFile(stream);
                        if (resourcesFile.AllEntriesAreStreams())
                        {
                            foreach (var(name, value) in resourcesFile)
                            {
                                string fileName = Path.Combine(name.Split('/').Select(p => CleanUpFileName(p)).ToArray());
                                string dirName  = Path.GetDirectoryName(fileName);
                                if (!string.IsNullOrEmpty(dirName) && directories.Add(dirName))
                                {
                                    Directory.CreateDirectory(Path.Combine(targetDirectory, dirName));
                                }
                                Stream entryStream = (Stream)value;
                                entryStream.Position = 0;
                                individualResources.AddRange(
                                    WriteResourceToFile(fileName, (string)name, entryStream));
                            }
                            decodedIntoIndividualFiles = true;
                        }
                        else
                        {
                            decodedIntoIndividualFiles = false;
                        }
                    } catch (BadImageFormatException) {
                        decodedIntoIndividualFiles = false;
                    } catch (EndOfStreamException) {
                        decodedIntoIndividualFiles = false;
                    }
                    if (decodedIntoIndividualFiles)
                    {
                        foreach (var entry in individualResources)
                        {
                            yield return(entry);
                        }
                    }
                    else
                    {
                        stream.Position = 0;
                        string fileName = GetFileNameForResource(r.Name);
                        foreach (var entry in WriteResourceToFile(fileName, r.Name, stream))
                        {
                            yield return(entry);
                        }
                    }
                }
                else
                {
                    string fileName = GetFileNameForResource(r.Name);
                    using (FileStream fs = new FileStream(Path.Combine(targetDirectory, fileName), FileMode.Create, FileAccess.Write)) {
                        stream.Position = 0;
                        stream.CopyTo(fs);
                    }
                    yield return(Tuple.Create("EmbeddedResource", fileName));
                }
            }
        }
Exemplo n.º 9
0
 protected virtual bool IsGacAssembly(Metadata.IAssemblyReference r, Metadata.PEFile asm)
 {
     return(false);
 }
Exemplo n.º 10
0
        void WriteProjectFile(TextWriter writer, IEnumerable <Tuple <string, string> > files, Metadata.PEFile module)
        {
            const string ns           = "http://schemas.microsoft.com/developer/msbuild/2003";
            string       platformName = GetPlatformName(module);
            Guid         guid         = this.ProjectGuid ?? Guid.NewGuid();

            using (XmlTextWriter w = new XmlTextWriter(writer)) {
                w.Formatting = Formatting.Indented;
                w.WriteStartDocument();
                w.WriteStartElement("Project", ns);
                w.WriteAttributeString("ToolsVersion", "4.0");
                w.WriteAttributeString("DefaultTargets", "Build");

                w.WriteStartElement("PropertyGroup");
                w.WriteElementString("ProjectGuid", guid.ToString("B").ToUpperInvariant());

                w.WriteStartElement("Configuration");
                w.WriteAttributeString("Condition", " '$(Configuration)' == '' ");
                w.WriteValue("Debug");
                w.WriteEndElement();                 // </Configuration>

                w.WriteStartElement("Platform");
                w.WriteAttributeString("Condition", " '$(Platform)' == '' ");
                w.WriteValue(platformName);
                w.WriteEndElement();                 // </Platform>

                if (module.Reader.PEHeaders.IsDll)
                {
                    w.WriteElementString("OutputType", "Library");
                }
                else
                {
                    switch (module.Reader.PEHeaders.PEHeader.Subsystem)
                    {
                    case Subsystem.WindowsGui:
                        w.WriteElementString("OutputType", "WinExe");
                        break;

                    case Subsystem.WindowsCui:
                        w.WriteElementString("OutputType", "Exe");
                        break;

                    default:
                        w.WriteElementString("OutputType", "Library");
                        break;
                    }
                }

                w.WriteElementString("LangVersion", LanguageVersion.ToString().Replace("CSharp", "").Replace('_', '.'));

                w.WriteElementString("AssemblyName", module.Name);
                bool            useTargetFrameworkAttribute = false;
                LanguageTargets languageTargets             = LanguageTargets.None;
                string          targetFramework             = module.Reader.DetectTargetFrameworkId();
                if (!string.IsNullOrEmpty(targetFramework))
                {
                    string[] frameworkParts      = targetFramework.Split(',');
                    string   frameworkIdentifier = frameworkParts.FirstOrDefault(a => !a.StartsWith("Version=", StringComparison.OrdinalIgnoreCase) && !a.StartsWith("Profile=", StringComparison.OrdinalIgnoreCase));
                    if (frameworkIdentifier != null)
                    {
                        w.WriteElementString("TargetFrameworkIdentifier", frameworkIdentifier);
                        switch (frameworkIdentifier)
                        {
                        case ".NETPortable":
                            languageTargets = LanguageTargets.Portable;
                            break;
                        }
                    }
                    string frameworkVersion = frameworkParts.FirstOrDefault(a => a.StartsWith("Version=", StringComparison.OrdinalIgnoreCase));
                    if (frameworkVersion != null)
                    {
                        w.WriteElementString("TargetFrameworkVersion", frameworkVersion.Substring("Version=".Length));
                        useTargetFrameworkAttribute = true;
                    }
                    string frameworkProfile = frameworkParts.FirstOrDefault(a => a.StartsWith("Profile=", StringComparison.OrdinalIgnoreCase));
                    if (frameworkProfile != null)
                    {
                        w.WriteElementString("TargetFrameworkProfile", frameworkProfile.Substring("Profile=".Length));
                    }
                }
                if (!useTargetFrameworkAttribute)
                {
                    switch (module.GetRuntime())
                    {
                    case Metadata.TargetRuntime.Net_1_0:
                        w.WriteElementString("TargetFrameworkVersion", "v1.0");
                        break;

                    case Metadata.TargetRuntime.Net_1_1:
                        w.WriteElementString("TargetFrameworkVersion", "v1.1");
                        break;

                    case Metadata.TargetRuntime.Net_2_0:
                        w.WriteElementString("TargetFrameworkVersion", "v2.0");
                        // TODO: Detect when .NET 3.0/3.5 is required
                        break;

                    default:
                        w.WriteElementString("TargetFrameworkVersion", "v4.0");
                        break;
                    }
                }
                w.WriteElementString("WarningLevel", "4");
                w.WriteElementString("AllowUnsafeBlocks", "True");

                w.WriteEndElement();                  // </PropertyGroup>

                w.WriteStartElement("PropertyGroup"); // platform-specific
                w.WriteAttributeString("Condition", " '$(Platform)' == '" + platformName + "' ");
                w.WriteElementString("PlatformTarget", platformName);
                if ((module.Reader.PEHeaders.CorHeader.Flags & CorFlags.Prefers32Bit) != 0)
                {
                    w.WriteElementString("Prefer32Bit", "True");
                }
                w.WriteEndElement();                  // </PropertyGroup> (platform-specific)

                w.WriteStartElement("PropertyGroup"); // Debug
                w.WriteAttributeString("Condition", " '$(Configuration)' == 'Debug' ");
                w.WriteElementString("OutputPath", "bin\\Debug\\");
                w.WriteElementString("DebugSymbols", "true");
                w.WriteElementString("DebugType", "full");
                w.WriteElementString("Optimize", "false");
                w.WriteEndElement();                  // </PropertyGroup> (Debug)

                w.WriteStartElement("PropertyGroup"); // Release
                w.WriteAttributeString("Condition", " '$(Configuration)' == 'Release' ");
                w.WriteElementString("OutputPath", "bin\\Release\\");
                w.WriteElementString("DebugSymbols", "true");
                w.WriteElementString("DebugType", "pdbonly");
                w.WriteElementString("Optimize", "true");
                w.WriteEndElement();                 // </PropertyGroup> (Release)


                w.WriteStartElement("ItemGroup");                 // References
                foreach (var r in module.AssemblyReferences)
                {
                    if (r.Name != "mscorlib")
                    {
                        w.WriteStartElement("Reference");
                        w.WriteAttributeString("Include", r.Name);
                        var asm = AssemblyResolver.Resolve(r);
                        if (!IsGacAssembly(r, asm))
                        {
                            if (asm != null)
                            {
                                w.WriteElementString("HintPath", asm.FileName);
                            }
                        }
                        w.WriteEndElement();
                    }
                }
                w.WriteEndElement();                 // </ItemGroup> (References)

                foreach (IGrouping <string, string> gr in (from f in files group f.Item2 by f.Item1 into g orderby g.Key select g))
                {
                    w.WriteStartElement("ItemGroup");
                    foreach (string file in gr.OrderBy(f => f, StringComparer.OrdinalIgnoreCase))
                    {
                        w.WriteStartElement(gr.Key);
                        w.WriteAttributeString("Include", file);
                        w.WriteEndElement();
                    }
                    w.WriteEndElement();
                }
                switch (languageTargets)
                {
                case LanguageTargets.Portable:
                    w.WriteStartElement("Import");
                    w.WriteAttributeString("Project", "$(MSBuildExtensionsPath32)\\Microsoft\\Portable\\$(TargetFrameworkVersion)\\Microsoft.Portable.CSharp.targets");
                    w.WriteEndElement();
                    break;

                default:
                    w.WriteStartElement("Import");
                    w.WriteAttributeString("Project", "$(MSBuildToolsPath)\\Microsoft.CSharp.targets");
                    w.WriteEndElement();
                    break;
                }

                w.WriteEndDocument();
            }
        }
Exemplo n.º 11
0
        ProjectId WriteProjectFile(TextWriter writer, IEnumerable <Tuple <string, string> > files, Metadata.PEFile module)
        {
            const string ns              = "http://schemas.microsoft.com/developer/msbuild/2003";
            string       platformName    = GetPlatformName(module);
            Guid         guid            = this.ProjectGuid ?? Guid.NewGuid();
            var          targetFramework = DetectTargetFramework(module);

            List <Guid> typeGuids = new List <Guid>();

            if (targetFramework.IsPortableClassLibrary)
            {
                typeGuids.Add(ProjectTypeGuids.PortableLibrary);
            }
            typeGuids.Add(ProjectTypeGuids.CSharpWindows);
            // TODO: .NET core support

            using (XmlTextWriter w = new XmlTextWriter(writer)) {
                w.Formatting = Formatting.Indented;
                w.WriteStartDocument();
                w.WriteStartElement("Project", ns);
                w.WriteAttributeString("ToolsVersion", "4.0");
                w.WriteAttributeString("DefaultTargets", "Build");

                w.WriteStartElement("PropertyGroup");
                w.WriteElementString("ProjectGuid", guid.ToString("B").ToUpperInvariant());
                w.WriteElementString("ProjectTypeGuids", string.Join(";", typeGuids.Select(g => g.ToString("B").ToUpperInvariant())));

                w.WriteStartElement("Configuration");
                w.WriteAttributeString("Condition", " '$(Configuration)' == '' ");
                w.WriteValue("Debug");
                w.WriteEndElement();                 // </Configuration>

                w.WriteStartElement("Platform");
                w.WriteAttributeString("Condition", " '$(Platform)' == '' ");
                w.WriteValue(platformName);
                w.WriteEndElement();                 // </Platform>

                if (module.Reader.PEHeaders.IsDll)
                {
                    w.WriteElementString("OutputType", "Library");
                }
                else
                {
                    switch (module.Reader.PEHeaders.PEHeader.Subsystem)
                    {
                    case Subsystem.WindowsGui:
                        w.WriteElementString("OutputType", "WinExe");
                        break;

                    case Subsystem.WindowsCui:
                        w.WriteElementString("OutputType", "Exe");
                        break;

                    default:
                        w.WriteElementString("OutputType", "Library");
                        break;
                    }
                }

                w.WriteElementString("LangVersion", LanguageVersion.ToString().Replace("CSharp", "").Replace('_', '.'));

                w.WriteElementString("AssemblyName", module.Name);
                if (targetFramework.TargetFrameworkIdentifier != null)
                {
                    w.WriteElementString("TargetFrameworkIdentifier", targetFramework.TargetFrameworkIdentifier);
                }
                if (targetFramework.TargetFrameworkVersion != null)
                {
                    w.WriteElementString("TargetFrameworkVersion", targetFramework.TargetFrameworkVersion);
                }
                if (targetFramework.TargetFrameworkProfile != null)
                {
                    w.WriteElementString("TargetFrameworkProfile", targetFramework.TargetFrameworkProfile);
                }
                w.WriteElementString("WarningLevel", "4");
                w.WriteElementString("AllowUnsafeBlocks", "True");

                if (StrongNameKeyFile != null)
                {
                    w.WriteElementString("SignAssembly", "True");
                    w.WriteElementString("AssemblyOriginatorKeyFile", Path.GetFileName(StrongNameKeyFile));
                }

                w.WriteEndElement();                  // </PropertyGroup>

                w.WriteStartElement("PropertyGroup"); // platform-specific
                w.WriteAttributeString("Condition", " '$(Platform)' == '" + platformName + "' ");
                w.WriteElementString("PlatformTarget", platformName);
                if (targetFramework.VersionNumber > 400 && platformName == "AnyCPU" && (module.Reader.PEHeaders.CorHeader.Flags & CorFlags.Prefers32Bit) == 0)
                {
                    w.WriteElementString("Prefer32Bit", "false");
                }
                w.WriteEndElement();                  // </PropertyGroup> (platform-specific)

                w.WriteStartElement("PropertyGroup"); // Debug
                w.WriteAttributeString("Condition", " '$(Configuration)' == 'Debug' ");
                w.WriteElementString("OutputPath", "bin\\Debug\\");
                w.WriteElementString("DebugSymbols", "true");
                w.WriteElementString("DebugType", "full");
                w.WriteElementString("Optimize", "false");
                w.WriteEndElement();                  // </PropertyGroup> (Debug)

                w.WriteStartElement("PropertyGroup"); // Release
                w.WriteAttributeString("Condition", " '$(Configuration)' == 'Release' ");
                w.WriteElementString("OutputPath", "bin\\Release\\");
                w.WriteElementString("DebugSymbols", "true");
                w.WriteElementString("DebugType", "pdbonly");
                w.WriteElementString("Optimize", "true");
                w.WriteEndElement();                 // </PropertyGroup> (Release)


                w.WriteStartElement("ItemGroup");                 // References
                foreach (var r in module.AssemblyReferences)
                {
                    if (r.Name != "mscorlib")
                    {
                        w.WriteStartElement("Reference");
                        w.WriteAttributeString("Include", r.Name);
                        var asm = AssemblyResolver.Resolve(r);
                        if (!IsGacAssembly(r, asm))
                        {
                            if (asm != null)
                            {
                                w.WriteElementString("HintPath", asm.FileName);
                            }
                        }
                        w.WriteEndElement();
                    }
                }
                w.WriteEndElement();                 // </ItemGroup> (References)

                foreach (IGrouping <string, string> gr in (from f in files group f.Item2 by f.Item1 into g orderby g.Key select g))
                {
                    w.WriteStartElement("ItemGroup");
                    foreach (string file in gr.OrderBy(f => f, StringComparer.OrdinalIgnoreCase))
                    {
                        w.WriteStartElement(gr.Key);
                        w.WriteAttributeString("Include", file);
                        w.WriteEndElement();
                    }
                    w.WriteEndElement();
                }
                if (targetFramework.IsPortableClassLibrary)
                {
                    w.WriteStartElement("Import");
                    w.WriteAttributeString("Project", "$(MSBuildExtensionsPath32)\\Microsoft\\Portable\\$(TargetFrameworkVersion)\\Microsoft.Portable.CSharp.targets");
                    w.WriteEndElement();
                }
                else
                {
                    w.WriteStartElement("Import");
                    w.WriteAttributeString("Project", "$(MSBuildToolsPath)\\Microsoft.CSharp.targets");
                    w.WriteEndElement();
                }

                w.WriteEndDocument();
            }

            return(new ProjectId(platformName, guid, ProjectTypeGuids.CSharpWindows));
        }