Пример #1
0
 public static extern IntPtr WIMCreateFile(
     string pszWimPath,
     WimOpenMode dwDesiredAccess,
     WimCreationMode dwCreationDisposition,
     WimCreationOptions dwFlagsAndAttributes,
     WimCompressionType dwCompressionType,
     out uint pdwCreationResult
     );
Пример #2
0
        public static bool CreateSetupMedia(
            string UUPPath,
            string LanguageCode,
            string OutputMediaPath,
            string OutputWindowsREPath,
            Common.CompressionType CompressionType,
            ProgressCallback progressCallback = null)
        {
            bool   result  = true;
            string BaseESD = null;

            (result, BaseESD) = FileLocator.LocateFilesForSetupMediaCreation(UUPPath, LanguageCode, progressCallback);
            if (!result)
            {
                goto exit;
            }

            WimCompressionType compression = WimCompressionType.None;

            switch (CompressionType)
            {
            case Common.CompressionType.LZMS:
                compression = WimCompressionType.Lzms;
                break;

            case Common.CompressionType.LZX:
                compression = WimCompressionType.Lzx;
                break;

            case Common.CompressionType.XPRESS:
                compression = WimCompressionType.Xpress;
                break;
            }

            //
            // Build installer
            //
            result = WindowsInstallerBuilder.BuildSetupMedia(BaseESD, OutputWindowsREPath, OutputMediaPath, compression, RunsAsAdministrator, LanguageCode, progressCallback);
            if (!result)
            {
                goto exit;
            }

exit:
            return(result);
        }
Пример #3
0
        /*private static void ProvisionMissingApps()
         * {
         *  string SourceEdition = "Professional";
         *  string TargetEdition = "PPIPro";
         *  string UUPPath = @"C:\Users\Gus\Downloads\19635.1_amd64_en-us_multi_6d892fb5\UUPs";
         *
         *  CompDBXmlClass.CompDB neutralCompDB = null;
         *
         *  if (Directory.EnumerateFiles(UUPPath, "*aggregatedmetadata*").Count() > 0)
         *  {
         *      using (CabinetHandler cabinet = new CabinetHandler(File.OpenRead(Directory.EnumerateFiles(UUPPath, "*aggregatedmetadata*").First())))
         *      {
         *          IEnumerable<string> potentialNeutralFiles = cabinet.Files.Where(x =>
         *          x.ToLower().Contains($"desktoptargetcompdb_neutral"));
         *
         *          if (potentialNeutralFiles.Count() == 0)
         *              goto exit;
         *
         *          using (CabinetHandler cabinet2 = new CabinetHandler(cabinet.OpenFile(potentialNeutralFiles.First())))
         *          {
         *              string xmlfile = cabinet2.Files.First();
         *              using (Stream xmlstream = cabinet2.OpenFile(xmlfile))
         *              {
         *                  neutralCompDB = CompDBXmlClass.DeserializeCompDB(xmlstream);
         *              }
         *          }
         *      }
         *  }
         *  else
         *  {
         *      IEnumerable<string> files = Directory.EnumerateFiles(UUPPath).Select(x => Path.GetFileName(x));
         *
         *      IEnumerable<string> potentialNeutralFiles = files.Where(x =>
         *             x.ToLower().Contains($"desktoptargetcompdb_neutral"));
         *
         *      if (potentialNeutralFiles.Count() == 0)
         *          goto exit;
         *
         *      using (CabinetHandler cabinet2 = new CabinetHandler(File.OpenRead(Path.Combine(UUPPath, potentialNeutralFiles.First()))))
         *      {
         *          string xmlfile = cabinet2.Files.First();
         *          using (Stream xmlstream = cabinet2.OpenFile(xmlfile))
         *          {
         *              neutralCompDB = CompDBXmlClass.DeserializeCompDB(xmlstream);
         *          }
         *      }
         *  }
         *
         *  var apppackages = neutralCompDB.Features.Feature.First(x => x.FeatureID == "BaseNeutral").Packages.Package.Select(x => x.ID.Split('_').Last()).Where(x => x.StartsWith("Microsoft.ModernApps.", StringComparison.InvariantCultureIgnoreCase));
         *
         *  bool sourceneedsclientpack = !SourceEdition.StartsWith("enterpriseg", StringComparison.InvariantCultureIgnoreCase) && !SourceEdition.StartsWith("ppipro", StringComparison.InvariantCultureIgnoreCase);
         *  bool sourceneedsclientnpack = SourceEdition.EndsWith("n", StringComparison.InvariantCultureIgnoreCase) || SourceEdition.EndsWith("neval", StringComparison.InvariantCultureIgnoreCase);
         *
         *  bool targetneedsclientpack = !TargetEdition.StartsWith("enterpriseg", StringComparison.InvariantCultureIgnoreCase) && !SourceEdition.StartsWith("ppipro", StringComparison.InvariantCultureIgnoreCase);
         *  bool targetneedsclientnpack = TargetEdition.EndsWith("n", StringComparison.InvariantCultureIgnoreCase) || TargetEdition.EndsWith("neval", StringComparison.InvariantCultureIgnoreCase);
         *
         *  List<string> SourceEditionApps = new List<string>();
         *  List<string> TargetEditionApps = new List<string>();
         *
         *  var potentialSourceEditionAppPackages = apppackages.Where(x => x.ToLower().Contains(SourceEdition.ToLower().TrimEnd('n')));
         *  if (potentialSourceEditionAppPackages.Count() > 0)
         *  {
         *      var apppackage = potentialSourceEditionAppPackages.First();
         *      string[] entries;
         *      imagingInterface.EnumerateFiles(Path.Combine(UUPPath, apppackage + ".esd"), 1, "", out entries);
         *      foreach (var entry in entries)
         *      {
         *          if (entry.ToLower() != "$filehashes$.dat")
         *          {
         *              string[] entries2;
         *              imagingInterface.EnumerateFiles(Path.Combine(UUPPath, apppackage + ".esd"), 1, entry, out entries2);
         *              var pkg = entries2.Where(x => x.ToLower() != "appxsignature.p7x" && x.ToLower() != "appxblockmap.xml" && x.ToLower() != "appxmetadata").First();
         *              var newpkg = pkg.Split('_')[0] + "_" + pkg.Split('_')[1] + "_neutral_~_" + pkg.Split('_')[4];
         *              bool isbundle = entries2.Any(x => x.ToLower() == "appxmetadata");
         *              SourceEditionApps.Add($"{entry}|{pkg}|{pkg.Split('_')[0]}|{newpkg}|{isbundle}");
         *          }
         *      }
         *  }
         *
         *  if (sourceneedsclientpack)
         *  {
         *      string package = "microsoft.modernapps.client.all.esd";
         *      if (sourceneedsclientnpack)
         *      {
         *          package = "microsoft.modernapps.clientn.all.esd";
         *      }
         *
         *      string[] entries;
         *      imagingInterface.EnumerateFiles(Path.Combine(UUPPath, package), 1, "", out entries);
         *      foreach (var entry in entries)
         *      {
         *          if (entry.ToLower() != "$filehashes$.dat")
         *          {
         *              string[] entries2;
         *              imagingInterface.EnumerateFiles(Path.Combine(UUPPath, package), 1, entry, out entries2);
         *              var pkg = entries2.Where(x => x.ToLower() != "appxsignature.p7x" && x.ToLower() != "appxblockmap.xml" && x.ToLower() != "appxmetadata").First();
         *              var newpkg = pkg.Split('_')[0] + "_" + pkg.Split('_')[1] + "_neutral_~_" + pkg.Split('_')[4];
         *              bool isbundle = entries2.Any(x => x.ToLower() == "appxmetadata");
         *              SourceEditionApps.Add($"{entry}|{pkg}|{pkg.Split('_')[0]}|{newpkg}|{isbundle}");
         *          }
         *      }
         *  }
         *
         *  var potentialTargetEditionAppPackages = apppackages.Where(x => x.ToLower().Contains(TargetEdition.ToLower().TrimEnd('n')));
         *  if (potentialTargetEditionAppPackages.Count() > 0)
         *  {
         *      var apppackage = potentialTargetEditionAppPackages.First();
         *      string[] entries;
         *      imagingInterface.EnumerateFiles(Path.Combine(UUPPath, apppackage + ".esd"), 1, "", out entries);
         *      foreach (var entry in entries)
         *      {
         *          if (entry.ToLower() != "$filehashes$.dat")
         *          {
         *              string[] entries2;
         *              imagingInterface.EnumerateFiles(Path.Combine(UUPPath, apppackage + ".esd"), 1, entry, out entries2);
         *              var pkg = entries2.Where(x => x.ToLower() != "appxsignature.p7x" && x.ToLower() != "appxblockmap.xml" && x.ToLower() != "appxmetadata").First();
         *              var newpkg = pkg.Split('_')[0] + "_" + pkg.Split('_')[1] + "_neutral_~_" + pkg.Split('_')[4];
         *              bool isbundle = entries2.Any(x => x.ToLower() == "appxmetadata");
         *              TargetEditionApps.Add($"{entry}|{pkg}|{pkg.Split('_')[0]}|{newpkg}|{isbundle}");
         *          }
         *      }
         *  }
         *
         *  if (targetneedsclientpack)
         *  {
         *      string package = "microsoft.modernapps.client.all.esd";
         *      if (targetneedsclientnpack)
         *      {
         *          package = "microsoft.modernapps.clientn.all.esd";
         *      }
         *
         *      string[] entries;
         *      imagingInterface.EnumerateFiles(Path.Combine(UUPPath, package), 1, "", out entries);
         *      foreach (var entry in entries)
         *      {
         *          if (entry.ToLower() != "$filehashes$.dat")
         *          {
         *              string[] entries2;
         *              imagingInterface.EnumerateFiles(Path.Combine(UUPPath, package), 1, entry, out entries2);
         *              var pkg = entries2.Where(x => x.ToLower() != "appxsignature.p7x" && x.ToLower() != "appxblockmap.xml" && x.ToLower() != "appxmetadata").First();
         *              var newpkg = pkg.Split('_')[0] + "_" + pkg.Split('_')[1] + "_neutral_~_" + pkg.Split('_')[4];
         *              bool isbundle = entries2.Any(x => x.ToLower() == "appxmetadata");
         *              TargetEditionApps.Add($"{entry}|{pkg}|{pkg.Split('_')[0]}|{newpkg}|{isbundle}");
         *          }
         *      }
         *  }
         *
         *  SourceEditionApps.Sort();
         *  TargetEditionApps.Sort();
         *
         *  Console.WriteLine("Source apps (" + SourceEdition + ")");
         *  foreach (var app in SourceEditionApps)
         *  {
         *      Console.WriteLine(app);
         *  }
         *  Console.WriteLine();
         *
         *  Console.WriteLine("Target apps (" + TargetEdition + ")");
         *  foreach (var app in TargetEditionApps)
         *  {
         *      Console.WriteLine(app);
         *  }
         *  Console.WriteLine();
         *
         *  var common = TargetEditionApps.Intersect(SourceEditionApps);
         *
         *  Console.WriteLine("The following apps must be uninstalled");
         *  foreach (var app in SourceEditionApps.Except(common))
         *  {
         *      Console.WriteLine(app);
         *  }
         *  Console.WriteLine();
         *
         *  Console.WriteLine("The following apps must be installed");
         *  foreach (var app in TargetEditionApps.Except(common))
         *  {
         *      Console.WriteLine(app);
         *  }
         *  Console.WriteLine();
         *
         * exit:
         *  return;
         * }*/

        public static bool CreateHackedEditionFromMountedImage(
            string UUPPath,
            string MediaPath,
            string MountedImagePath,
            string EditionID,
            string OutputInstallImage,
            Common.CompressionType CompressionType,
            ProgressCallback progressCallback = null)
        {
            bool result = true;

            progressCallback?.Invoke(Common.ProcessPhase.ApplyingImage, true, 0, "Applying " + EditionID + " - Package Swap");

            progressCallback?.Invoke(Common.ProcessPhase.ApplyingImage, true, 0, "Getting serial for " + EditionID);
            string productinifilepath = Path.Combine(MediaPath, "sources", "product.ini");

            var     parser = new FileIniDataParser();
            IniData data   = parser.ReadFile(productinifilepath);

            string serial = data["cmi"].First(x => x.KeyName.ToLower() == EditionID.ToLower()).Value;

            progressCallback?.Invoke(Common.ProcessPhase.ApplyingImage, true, 0, "Serial: " + serial);

            progressCallback?.Invoke(Common.ProcessPhase.ApplyingImage, true, 0, "Getting current edition");
            string SourceEdition = DismOperations.GetCurrentEdition(MountedImagePath);

            progressCallback?.Invoke(Common.ProcessPhase.ApplyingImage, true, 0, "Current edition is: " + SourceEdition);

            progressCallback?.Invoke(Common.ProcessPhase.ApplyingImage, true, 0, "Getting wim info for: " + OutputInstallImage);
            WIMInformationXML.WIM wiminfo;
            result = imagingInterface.GetWIMInformation(OutputInstallImage, out wiminfo);
            if (!result)
            {
                goto exit;
            }

            progressCallback?.Invoke(Common.ProcessPhase.ApplyingImage, true, 0, "Searching index for : " + SourceEdition);
            var srcimage = wiminfo.IMAGE.First(x =>
            {
                var img = x;
                var win = img.WINDOWS;
                var ed  = win.EDITIONID;
                return(ed.Equals(SourceEdition, StringComparison.InvariantCultureIgnoreCase));
            });
            var index        = int.Parse(srcimage.INDEX);
            var languagecode = srcimage.WINDOWS.LANGUAGES.DEFAULT;

            progressCallback?.Invoke(Common.ProcessPhase.ApplyingImage, true, 0, "Source index: " + index);
            progressCallback?.Invoke(Common.ProcessPhase.ApplyingImage, true, 0, "Source language: " + languagecode);

            WimCompressionType compression = WimCompressionType.None;

            switch (CompressionType)
            {
            case Common.CompressionType.LZMS:
                compression = WimCompressionType.Lzms;
                break;

            case Common.CompressionType.LZX:
                compression = WimCompressionType.Lzx;
                break;

            case Common.CompressionType.XPRESS:
                compression = WimCompressionType.Xpress;
                break;
            }

            //
            // Perform edition hack
            //
            string servicingPath = Path.Combine(MountedImagePath, "Windows", "servicing", "Packages");
            string manifest      = $"Microsoft-Windows-{SourceEdition}Edition~31bf3856ad364e35~*~~10.0.*.*.mum";
            string catalog       = $"Microsoft-Windows-{SourceEdition}Edition~31bf3856ad364e35~*~~10.0.*.*.cat";
            string manifestPath  = Directory.EnumerateFiles(servicingPath, manifest).First();
            string catalogPath   = Directory.EnumerateFiles(servicingPath, catalog).First();

            bool LTSB = false;

            if (EditionID.ToLower().StartsWith("enterpriseg") ||
                EditionID.ToLower().StartsWith("enterprises") ||
                EditionID.ToLower().StartsWith("iotenterprises"))
            {
                LTSB = true;
            }

            bool HasEditionPack = Directory.EnumerateFiles(UUPPath, "*.esd", SearchOption.AllDirectories).Any(x =>
                                                                                                              Path.GetFileName(x).Equals($"microsoft-windows-editionpack-{EditionID}-package.esd", StringComparison.InvariantCulture)
                                                                                                              );

            progressCallback?.Invoke(Common.ProcessPhase.ApplyingImage, true, 0, "Has edition pack: " + HasEditionPack);

            string TemporaryFolder = Path.GetTempFileName();

            File.Delete(TemporaryFolder);
            Directory.CreateDirectory(TemporaryFolder);

            string SxSFolder = Path.Combine(TemporaryFolder, "SxS");

            Directory.CreateDirectory(SxSFolder);

            //
            // Build reconstructed edition xml
            //
            progressCallback?.Invoke(Common.ProcessPhase.ApplyingImage, true, 0, "Generating edition manifest");
            string packageFilter = $"microsoft-windows-edition*{EditionID}-*.esd";
            var    packages      = Directory.EnumerateFiles(UUPPath, packageFilter, SearchOption.AllDirectories);

            string manifestFileName = Path.GetFileName(manifestPath).Replace(SourceEdition, EditionID);
            string catalogFileName  = Path.GetFileName(catalogPath).Replace(SourceEdition, EditionID);

            string newManifestPath = Path.Combine(SxSFolder, manifestFileName);
            string newCatalogPath  = Path.Combine(SxSFolder, catalogFileName);

            File.Copy(manifestPath, newManifestPath);
            File.Copy(catalogPath, newCatalogPath);

            string ManifestContent = File.ReadAllText(newManifestPath);

            ManifestContent = ManifestContent.Replace($"EditionSpecific-{SourceEdition}", $"EditionSpecific-{EditionID}").Replace($"Windows {SourceEdition} Edition", $"Windows {EditionID} Edition").Replace($"Microsoft-Windows-{SourceEdition}Edition", $"Microsoft-Windows-{EditionID}Edition");

            if (HasEditionPack)
            {
                ManifestContent = ManifestContent.Replace($"EditionPack-{SourceEdition}", $"EditionPack-{EditionID}");
            }

            File.WriteAllText(newManifestPath, ManifestContent);

            if (LTSB)
            {
                AssemblyManifestHandler.RemoveNonLTSBPackages(newManifestPath);
            }

            // Cleanup WOW64
            if (!packages.Any(x => x.Equals($"microsoft-windows-editionspecific-{EditionID}-wow64-package.esd", StringComparison.InvariantCultureIgnoreCase)))
            {
                progressCallback?.Invoke(Common.ProcessPhase.ApplyingImage, true, 0, "Cleaning up WOW64");
                AssemblyManifestHandler.RemoveWOW64Package(newManifestPath, $"microsoft-windows-editionspecific-{EditionID}-wow64-package");
            }

            //
            // Expand LP to folder
            //
            if (LPFolder == null)
            {
                LPFolder = Path.GetTempFileName();
                File.Delete(LPFolder);
                Directory.CreateDirectory(LPFolder);

                string lpfilter1 = $"*fre_client_{languagecode}_lp.cab";
                var    paths     = Directory.EnumerateFiles(UUPPath, lpfilter1, SearchOption.AllDirectories);
                if (paths.Count() > 0)
                {
                    string lppackage = paths.First();
                    void ProgressCallback(int percent, string file)
                    {
                        progressCallback?.Invoke(Common.ProcessPhase.PreparingFiles, false, percent, "Unpacking " + file + "...");
                    };

                    CabinetHandler.ExpandFiles(lppackage, LPFolder, ProgressCallback);
                }
                else
                {
                    string lpfilter2 = $"microsoft-windows-client-languagepack-package_{languagecode}-*-{languagecode}.esd";
                    string lppackage = "";
                    if (Directory.EnumerateFiles(UUPPath, lpfilter2, SearchOption.AllDirectories).Count() > 0)
                    {
                        lppackage = Directory.EnumerateFiles(UUPPath, lpfilter2, SearchOption.AllDirectories).First();
                    }
                    else
                    {
                        lpfilter2 = $"microsoft-windows-client-languagepack-package_{languagecode}~*~{languagecode}~.esd";
                        lppackage = Directory.EnumerateFiles(UUPPath, lpfilter2, SearchOption.AllDirectories).First();
                    }

                    result = imagingInterface.ApplyImage(lppackage, 1, LPFolder, PreserveACL: false, progressCallback: callback2);
                    if (!result)
                    {
                        goto exit;
                    }
                }
            }

            //
            // Expand Edition related packages to SxS folder
            //
            foreach (var package in packages)
            {
                result = imagingInterface.ApplyImage(package, 1, SxSFolder, PreserveACL: false, progressCallback: callback2);
                if (!result)
                {
                    goto exit;
                }

                if (File.Exists(Path.Combine(SxSFolder, "update.mum")))
                {
                    var    assembly = AssemblyManifestHandler.Deserialize(File.ReadAllText(Path.Combine(SxSFolder, "update.mum")));
                    string cbsKey   = assembly.AssemblyIdentity.Name + "~" + assembly.AssemblyIdentity.PublicKeyToken + "~" + assembly.AssemblyIdentity.ProcessorArchitecture + "~" + (assembly.AssemblyIdentity.Language.ToLower() == "neutral" ? "" : assembly.AssemblyIdentity.Language) + "~" + assembly.AssemblyIdentity.Version;
                    if (!File.Exists(Path.Combine(SxSFolder, cbsKey + ".mum")))
                    {
                        File.Move(Path.Combine(SxSFolder, "update.mum"), Path.Combine(SxSFolder, cbsKey + ".mum"));
                    }
                    else
                    {
                        File.Delete(Path.Combine(SxSFolder, "update.mum"));
                    }

                    if (File.Exists(Path.Combine(SxSFolder, "update.cat")))
                    {
                        if (!File.Exists(Path.Combine(SxSFolder, cbsKey + ".cat")))
                        {
                            File.Move(Path.Combine(SxSFolder, "update.cat"), Path.Combine(SxSFolder, cbsKey + ".cat"));
                        }
                        else
                        {
                            File.Delete(Path.Combine(SxSFolder, "update.cat"));
                        }
                    }
                }
                File.Delete(Path.Combine(SxSFolder, "$filehashes$.dat"));
            }

            //
            // Generate unattend
            //
            progressCallback?.Invoke(Common.ProcessPhase.ApplyingImage, true, 0, "Generating unattend");
            string arch = manifestFileName.Split('~')[2];
            string ver  = manifestFileName.Split('~')[4].Replace(".mum", "");

            bool removeogedition = true;

            // TODO: get these from matrix
            //
            if (SourceEdition.Equals("core", StringComparison.InvariantCultureIgnoreCase))
            {
                if (EditionID.Equals("corecountryspecific", StringComparison.InvariantCultureIgnoreCase))
                {
                    removeogedition = false;
                }
            }
            if (SourceEdition.Equals("professional", StringComparison.InvariantCultureIgnoreCase))
            {
                if (EditionID.Equals("core", StringComparison.InvariantCultureIgnoreCase))
                {
                    removeogedition = false;
                }
            }
            if (SourceEdition.Equals("professionaln", StringComparison.InvariantCultureIgnoreCase))
            {
                if (EditionID.Equals("coren", StringComparison.InvariantCultureIgnoreCase))
                {
                    removeogedition = false;
                }
            }
            if (SourceEdition.Equals("core", StringComparison.InvariantCultureIgnoreCase))
            {
                if (EditionID.Equals("starter", StringComparison.InvariantCultureIgnoreCase))
                {
                    removeogedition = false;
                }
            }
            if (SourceEdition.Equals("coren", StringComparison.InvariantCultureIgnoreCase))
            {
                if (EditionID.Equals("startern", StringComparison.InvariantCultureIgnoreCase))
                {
                    removeogedition = false;
                }
            }

            string unattend = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
                              "<unattend xmlns=\"urn:schemas-microsoft-com:unattend\">\n" +
                              "    <servicing>\n";

            if (!removeogedition)
            {
                unattend +=
                    "        <package action=\"stage\">\n" +
                    $"            <assemblyIdentity name=\"Microsoft-Windows-{SourceEdition}Edition\" version=\"{ver}\" processorArchitecture=\"{arch}\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" />\n" +
                    "        </package>\n";
            }

            unattend +=
                "        <package action=\"stage\">\n" +
                $"            <assemblyIdentity name=\"Microsoft-Windows-{EditionID}Edition\" version=\"{ver}\" processorArchitecture=\"{arch}\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" />\n" +
                $"            <source location=\"{newManifestPath}\" />\n" +
                "        </package>\n";

            if (removeogedition)
            {
                unattend +=
                    "        <package action=\"remove\">\n" +
                    $"            <assemblyIdentity name=\"Microsoft-Windows-{SourceEdition}Edition\" version=\"{ver}\" processorArchitecture=\"{arch}\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" />\n" +
                    "        </package>\n";
            }

            unattend +=
                "        <package action=\"install\">\n" +
                $"            <assemblyIdentity name=\"Microsoft-Windows-{EditionID}Edition\" version=\"{ver}\" processorArchitecture=\"{arch}\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" />\n" +
                "        </package>\n" +
                "        <package action=\"install\">\n" +
                $"            <assemblyIdentity name=\"Microsoft-Windows-Client-LanguagePack-Package\" version=\"{ver}\" processorArchitecture=\"{arch}\" publicKeyToken=\"31bf3856ad364e35\" language=\"{languagecode}\" />\n" +
                $"            <source location=\"{LPFolder}\\update.mum\" />\n" +
                "        </package>\n" +
                "    </servicing>\n" +
                "</unattend>";

            string unattendPath = Path.Combine(TemporaryFolder, "unattend.xml");

            File.WriteAllText(unattendPath, unattend);

            //
            // Backup OEMDefaultAssociations
            //
            progressCallback?.Invoke(Common.ProcessPhase.ApplyingImage, true, 0, "Backing up OEMDefaultAssociations");

            bool HandleOEMDefaultAssociationsXml = File.Exists(Path.Combine(MountedImagePath, "Windows", "System32", "OEMDefaultAssociations.xml"));
            bool HandleOEMDefaultAssociationsDll = File.Exists(Path.Combine(MountedImagePath, "Windows", "System32", "OEMDefaultAssociations.dll"));

            string OEMDefaultAssociationsXml = Path.GetTempFileName();
            string OEMDefaultAssociationsDll = Path.GetTempFileName();

            File.Delete(OEMDefaultAssociationsXml);
            File.Delete(OEMDefaultAssociationsDll);

            string OEMDefaultAssociationsXmlInImage = Path.Combine(MountedImagePath, "Windows", "System32", "OEMDefaultAssociations.xml");
            string OEMDefaultAssociationsDllInImage = Path.Combine(MountedImagePath, "Windows", "System32", "OEMDefaultAssociations.dll");

            if (HandleOEMDefaultAssociationsXml)
            {
                File.Copy(OEMDefaultAssociationsXmlInImage, OEMDefaultAssociationsXml);
            }

            if (HandleOEMDefaultAssociationsDll)
            {
                File.Copy(OEMDefaultAssociationsDllInImage, OEMDefaultAssociationsDll);
            }

            //
            // Apply unattend
            //
            progressCallback?.Invoke(Common.ProcessPhase.ApplyingImage, true, 0, "Applying unattend");
            DismOperations.ApplyUnattend(MountedImagePath, unattendPath);

            //
            // Restore OEMDefaultAssociations
            //
            progressCallback?.Invoke(Common.ProcessPhase.ApplyingImage, true, 0, "Restoring up OEMDefaultAssociations");

            if (HandleOEMDefaultAssociationsXml)
            {
                if (!File.Exists(OEMDefaultAssociationsXmlInImage))
                {
                    File.Move(OEMDefaultAssociationsXml, OEMDefaultAssociationsXmlInImage);
                }
            }

            if (HandleOEMDefaultAssociationsDll)
            {
                if (!File.Exists(OEMDefaultAssociationsDllInImage))
                {
                    File.Move(OEMDefaultAssociationsDll, OEMDefaultAssociationsDllInImage);
                }
            }

            //
            // Copy edition xml
            //
            progressCallback?.Invoke(Common.ProcessPhase.ApplyingImage, true, 0, "Handling Edition Unattend XML");
            string editionXml            = Path.Combine(MountedImagePath, "Windows", "servicing", "Editions", $"{EditionID}Edition.xml");
            string desintationEditionXml = Path.Combine(MountedImagePath, "Windows", $"{EditionID}.xml");

            File.Copy(editionXml, desintationEditionXml);

            //
            // Delete old edition xml
            //
            File.Delete(Path.Combine(MountedImagePath, "Windows", $"{SourceEdition}.xml"));

            //
            // Apply edition xml as unattend
            //
            progressCallback?.Invoke(Common.ProcessPhase.ApplyingImage, true, 0, "Applying Edition Unattend XML");
            DismOperations.ApplyUnattend(MountedImagePath, desintationEditionXml);

            //
            // Install correct product key
            //
            progressCallback?.Invoke(Common.ProcessPhase.ApplyingImage, true, 0, "Installing product key");

            DismOperations.SetProductKey(MountedImagePath, serial);

            //
            // Application handling
            //
            progressCallback?.Invoke(Common.ProcessPhase.ApplyingImage, true, 0, "Installing apps");

            //////////////////////// TODO ////////////////////////

            //
            // Cleanup
            //
            progressCallback?.Invoke(Common.ProcessPhase.ApplyingImage, true, 0, "Cleaning up");
            Directory.Delete(TemporaryFolder, true);
            CleanupLanguagePackFolderIfRequired();

            void callback2(string Operation, int ProgressPercentage, bool IsIndeterminate)
            {
                progressCallback?.Invoke(Common.ProcessPhase.CapturingImage, IsIndeterminate, ProgressPercentage, Operation);
            };

            string name = $"Windows 10 {EditionID}";

            if (Constants.FriendlyEditionNames.Any(x => x.Key.Equals(EditionID, StringComparison.InvariantCultureIgnoreCase)))
            {
                name = Constants.FriendlyEditionNames.First(x => x.Key.Equals(EditionID, StringComparison.InvariantCultureIgnoreCase)).Value;
            }

            result = imagingInterface.CaptureImage(
                OutputInstallImage,
                name,
                name,
                EditionID,
                MountedImagePath,
                name,
                name,
                compression,
                progressCallback: callback2,
                UpdateFrom: index);

            if (!result)
            {
                goto exit;
            }

            WIMInformationXML.IMAGE tmpImageInfo;
            result = imagingInterface.GetWIMImageInformation(OutputInstallImage, wiminfo.IMAGE.Count + 1, out tmpImageInfo);
            if (!result)
            {
                goto exit;
            }

            var sku = tmpImageInfo.WINDOWS.EDITIONID;

            tmpImageInfo.WINDOWS           = srcimage.WINDOWS;
            tmpImageInfo.WINDOWS.EDITIONID = sku;
            tmpImageInfo.FLAGS             = sku;
            tmpImageInfo.NAME               = name;
            tmpImageInfo.DESCRIPTION        = name;
            tmpImageInfo.DISPLAYNAME        = name;
            tmpImageInfo.DISPLAYDESCRIPTION = name;

            result = imagingInterface.SetWIMImageInformation(OutputInstallImage, wiminfo.IMAGE.Count + 1, tmpImageInfo);
            if (!result)
            {
                goto exit;
            }

exit:
            return(result);
        }
Пример #4
0
        public static bool CreateUpgradedEditionFromMountedImage(
            string MountedImagePath,
            string EditionID,
            string OutputInstallImage,
            bool IsVirtual,
            Common.CompressionType CompressionType,
            ProgressCallback progressCallback = null)
        {
            bool result = true;

            string SourceEdition = DismOperations.GetCurrentEdition(MountedImagePath);

            WIMInformationXML.WIM wiminfo;
            result = imagingInterface.GetWIMInformation(OutputInstallImage, out wiminfo);
            if (!result)
            {
                goto exit;
            }

            var srcimage = wiminfo.IMAGE.First(x => x.WINDOWS.EDITIONID.Equals(SourceEdition, StringComparison.InvariantCultureIgnoreCase));
            var index    = int.Parse(srcimage.INDEX);

            WimCompressionType compression = WimCompressionType.None;

            switch (CompressionType)
            {
            case Common.CompressionType.LZMS:
                compression = WimCompressionType.Lzms;
                break;

            case Common.CompressionType.LZX:
                compression = WimCompressionType.Lzx;
                break;

            case Common.CompressionType.XPRESS:
                compression = WimCompressionType.Xpress;
                break;
            }

            void callback(bool IsIndeterminate, int ProgressInPercentage, string SubOperation)
            {
                progressCallback?.Invoke(Common.ProcessPhase.ApplyingImage, IsIndeterminate, ProgressInPercentage, SubOperation);
            };

            DismOperations.SetTargetEdition(MountedImagePath, EditionID, callback);

            void callback2(string Operation, int ProgressPercentage, bool IsIndeterminate)
            {
                progressCallback?.Invoke(Common.ProcessPhase.CapturingImage, IsIndeterminate, ProgressPercentage, Operation);
            };

            string name = $"Windows 10 {EditionID}";

            if (Constants.FriendlyEditionNames.Any(x => x.Key.Equals(EditionID, StringComparison.InvariantCultureIgnoreCase)))
            {
                name = Constants.FriendlyEditionNames.First(x => x.Key.Equals(EditionID, StringComparison.InvariantCultureIgnoreCase)).Value;
            }

            result = imagingInterface.CaptureImage(
                OutputInstallImage,
                name,
                name,
                EditionID,
                MountedImagePath,
                name,
                name,
                compression,
                progressCallback: callback2,
                UpdateFrom: index);

            if (!result)
            {
                goto exit;
            }

            WIMInformationXML.IMAGE tmpImageInfo;
            result = imagingInterface.GetWIMImageInformation(OutputInstallImage, wiminfo.IMAGE.Count + 1, out tmpImageInfo);
            if (!result)
            {
                goto exit;
            }

            var sku = tmpImageInfo.WINDOWS.EDITIONID;

            tmpImageInfo.WINDOWS           = srcimage.WINDOWS;
            tmpImageInfo.WINDOWS.EDITIONID = sku;
            tmpImageInfo.FLAGS             = sku;

            tmpImageInfo.NAME               = name;
            tmpImageInfo.DESCRIPTION        = name;
            tmpImageInfo.DISPLAYNAME        = name;
            tmpImageInfo.DISPLAYDESCRIPTION = name;

            result = imagingInterface.SetWIMImageInformation(OutputInstallImage, wiminfo.IMAGE.Count + 1, tmpImageInfo);
            if (!result)
            {
                goto exit;
            }

            if (IsVirtual)
            {
                File.Delete(Path.Combine(MountedImagePath, "Windows", $"{EditionID}.xml"));
            }

exit:
            return(result);
        }
Пример #5
0
        private static bool PerformComponentCleanupOnPEImage(
            string MediaPath,
            WimCompressionType compressionType,
            WIMInformationXML.IMAGE image,
            ProgressCallback progressCallback = null
            )
        {
            using (VirtualDiskSession vhdsession = new VirtualDiskSession())
            {
                string ospath = vhdsession.GetMountedPath();

                //
                // Apply the RE image to our ospath, in this case our VHD
                //
                void callback(string Operation, int ProgressPercentage, bool IsIndeterminate)
                {
                    progressCallback?.Invoke(Common.ProcessPhase.CreatingWindowsInstaller, IsIndeterminate, ProgressPercentage, Operation);
                }

                bool result = imagingInterface.ApplyImage(Path.Combine(MediaPath, "sources", "boot.wim"), 1, ospath, progressCallback: callback);
                if (!result)
                {
                    goto exit;
                }

                File.Delete(Path.Combine(MediaPath, "sources", "boot.wim"));

                result = RunDismComponentRemovalOperation(ospath, progressCallback);
                if (!result)
                {
                    goto exit;
                }

                //
                // Cleanup leftovers for WLAN
                //
                progressCallback?.Invoke(Common.ProcessPhase.CreatingWindowsInstaller, true, 0, "Cleaning up leftovers");

                string winsxsfolder    = Path.Combine(ospath, "Windows", "WinSxS");
                string winsxsManFolder = Path.Combine(winsxsfolder, "Manifests");

                IEnumerable <string> directoriesToCleanOut = Directory.EnumerateDirectories(winsxsfolder, "*_dual_netnwifi.inf_31bf3856ad364e35_*", SearchOption.TopDirectoryOnly);
                IEnumerable <string> manifestsToCleanOut   = Directory.EnumerateFiles(winsxsManFolder, "*_dual_netnwifi.inf_31bf3856ad364e35_*", SearchOption.TopDirectoryOnly);

                foreach (string dir in directoriesToCleanOut)
                {
                    try
                    {
                        progressCallback?.Invoke(Common.ProcessPhase.CreatingWindowsInstaller, true, 0, "Deleting " + dir);
                        TakeOwn.TakeOwnDirectory(dir);
                        Directory.Delete(dir, true);
                    }
                    catch { }
                }

                foreach (string file in manifestsToCleanOut)
                {
                    try
                    {
                        progressCallback?.Invoke(Common.ProcessPhase.CreatingWindowsInstaller, true, 0, "Deleting " + file);
                        TakeOwn.TakeOwnFile(file);
                        File.Delete(file);
                    }
                    catch { }
                }

                //
                // Add missing files from the setup media root
                //
                progressCallback?.Invoke(Common.ProcessPhase.CreatingWindowsInstaller, true, 0, "Adding missing files");

                if (!File.Exists(Path.Combine(ospath, "Windows", "System32", "ReAgent.dll")))
                {
                    File.Copy(Path.Combine(MediaPath, "sources", "ReAgent.dll"), Path.Combine(ospath, "Windows", "System32", "ReAgent.dll"));
                }
                if (!File.Exists(Path.Combine(ospath, "Windows", "System32", "unattend.dll")))
                {
                    File.Copy(Path.Combine(MediaPath, "sources", "unattend.dll"), Path.Combine(ospath, "Windows", "System32", "unattend.dll"));
                }
                if (!File.Exists(Path.Combine(ospath, "Windows", "System32", "wpx.dll")))
                {
                    File.Copy(Path.Combine(MediaPath, "sources", "wpx.dll"), Path.Combine(ospath, "Windows", "System32", "wpx.dll"));
                }

                result = imagingInterface.CaptureImage(
                    Path.Combine(MediaPath, "sources", "boot.wim"),
                    image.NAME,
                    image.DESCRIPTION,
                    image.FLAGS,
                    ospath,
                    progressCallback: callback,
                    compressionType: compressionType);
                if (!result)
                {
                    goto exit;
                }

exit:
                return(result);
            }
        }
Пример #6
0
        private static bool PreparePEImage(
            string BaseESD,
            string OutputWinREPath,
            string MediaPath,
            WimCompressionType compressionType,
            string LanguageCode,
            ProgressCallback progressCallback = null
            )
        {
            //
            // Export the RE image to our re path, in this case a WIM
            //
            void callback(string Operation, int ProgressPercentage, bool IsIndeterminate)
            {
                progressCallback?.Invoke(Common.ProcessPhase.CreatingWindowsInstaller, IsIndeterminate, ProgressPercentage, Operation);
            }

            bool result = imagingInterface.ExportImage(BaseESD, OutputWinREPath, 2, compressionType: compressionType, progressCallback: callback);

            if (!result)
            {
                goto exit;
            }

            WIMInformationXML.IMAGE image;
            result = imagingInterface.GetWIMImageInformation(OutputWinREPath, 1, out image);
            if (!result)
            {
                goto exit;
            }

            if (image.WINDOWS.LANGUAGES == null)
            {
                image.WINDOWS.LANGUAGES = new WIMInformationXML.LANGUAGES()
                {
                    LANGUAGE = LanguageCode,
                    FALLBACK = new WIMInformationXML.FALLBACK()
                    {
                        LANGUAGE = LanguageCode,
                        Text     = "en-US"
                    },
                    DEFAULT = LanguageCode
                };

                result = imagingInterface.SetWIMImageInformation(OutputWinREPath, 1, image);
                if (!result)
                {
                    goto exit;
                }
            }

            progressCallback?.Invoke(Common.ProcessPhase.CreatingWindowsInstaller, true, 0, "Marking image as bootable");
            result = imagingInterface.MarkImageAsBootable(OutputWinREPath, 1);
            if (!result)
            {
                goto exit;
            }

            string bootwim = Path.Combine(MediaPath, "sources", "boot.wim");

            File.Copy(OutputWinREPath, bootwim);

            //
            // Cleanup WinPE Shell directive
            //
            string sys32      = Path.Combine("Windows", "System32");
            string peshellini = Path.Combine(sys32, "winpeshl.ini");

            // Ignore return result
            imagingInterface.DeleteFileFromImage(bootwim, 1, peshellini, progressCallback: callback);

            //
            // Cleanup log file from RE conversion phase mentions
            //
            try
            {
                progressCallback?.Invoke(Common.ProcessPhase.CreatingWindowsInstaller, true, 0, "Cleaning log files");
                string logfile     = Path.GetTempFileName();
                string pathinimage = Path.Combine("Windows", "INF", "setupapi.offline.log");

                bool cresult = imagingInterface.ExtractFileFromImage(bootwim, 1, pathinimage, logfile);

                if (cresult)
                {
                    string[] lines = File.ReadAllLines(logfile);

                    int           bootsessioncount = 0;
                    List <string> finallines       = new List <string>();
                    foreach (string line in lines)
                    {
                        if (line.StartsWith("[Boot Session: ", StringComparison.InvariantCultureIgnoreCase))
                        {
                            bootsessioncount++;
                        }
                        if (bootsessioncount == 2)
                        {
                            finallines.RemoveAt(finallines.Count - 1);
                            File.WriteAllLines(logfile, finallines);
                            // Ignore return result
                            imagingInterface.AddFileToImage(bootwim, 1, logfile, pathinimage, progressCallback: callback);
                            break;
                        }
                        finallines.Add(line);
                    }
                }
            }
            catch { }

            //
            // Disable UMCI
            //
            progressCallback?.Invoke(Common.ProcessPhase.CreatingWindowsInstaller, true, 0, "Disabling UMCI");
            string tempSystemHiveBackup = Path.GetTempFileName();

            result = imagingInterface.ExtractFileFromImage(bootwim, 1, Constants.SYSTEM_Hive_Location, tempSystemHiveBackup);
            if (!result)
            {
                goto cleanup;
            }

            result = RegistryOperations.ModifyBootGlobalRegistry(tempSystemHiveBackup);
            if (!result)
            {
                goto cleanup;
            }

            result = imagingInterface.AddFileToImage(bootwim, 1, tempSystemHiveBackup, Constants.SYSTEM_Hive_Location, progressCallback: callback);
            if (!result)
            {
                goto cleanup;
            }

cleanup:
            File.Delete(tempSystemHiveBackup);

exit:
            return(result);
        }
Пример #7
0
        // 6 progress bars
        public static bool BuildSetupMedia(
            string BaseESD,
            string OutputWinREPath,
            string MediaPath,
            WimCompressionType compressionType,
            bool RunsAsAdministrator,
            string LanguageCode,
            ProgressCallback progressCallback = null
            )
        {
            //
            // First create the setup media base, minus install.wim and boot.wim
            //
            bool result = CreateSetupMediaRoot(BaseESD, MediaPath, progressCallback);

            if (!result)
            {
                goto exit;
            }

            //
            // Gather information about the Windows Recovery Environment image so we can transplant it later
            // into our new images
            //
            WIMInformationXML.IMAGE image;
            result = imagingInterface.GetWIMImageInformation(BaseESD, 2, out image);
            if (!result)
            {
                goto exit;
            }

            //
            // Gather the architecture string under parenthesis for the new images we are creating
            //
            string ArchitectureInNameAndDescription = image.NAME.Split('(')[1].Replace(")", "");

            string BootFirstImageName  = $"Microsoft Windows PE ({ArchitectureInNameAndDescription})";
            string BootSecondImageName = $"Microsoft Windows Setup ({ArchitectureInNameAndDescription})";
            string BootFirstImageFlag  = "9";
            string BootSecondImageFlag = "2";

            //
            // Bootable wim files must not be lzms
            //
            if (compressionType == WimCompressionType.Lzms)
            {
                compressionType = WimCompressionType.Lzx;
            }

            void callback(string Operation, int ProgressPercentage, bool IsIndeterminate)
            {
                progressCallback?.Invoke(Common.ProcessPhase.CreatingWindowsInstaller, IsIndeterminate, ProgressPercentage, Operation);
            }

            //
            // Prepare our base PE image which will serve as a basis for all subsequent operations
            // This function also generates WinRE
            //
            result = PreparePEImage(BaseESD, OutputWinREPath, MediaPath, compressionType, LanguageCode, progressCallback);
            if (!result)
            {
                goto exit;
            }

            //
            // If we are running as administrator, perform additional component cleanup
            //
            if (RunsAsAdministrator)
            {
                result = PerformComponentCleanupOnPEImage(MediaPath, compressionType, image, progressCallback);
                if (!result)
                {
                    goto exit;
                }
            }

            string bootwim = Path.Combine(MediaPath, "sources", "boot.wim");

            string tmpwimcopy = Path.GetTempFileName();

            File.Delete(tmpwimcopy);
            File.Copy(bootwim, tmpwimcopy);

            //
            // Duplicate the boot image so we have two of them
            //
            result = imagingInterface.ExportImage(tmpwimcopy, bootwim, 1, compressionType: compressionType, progressCallback: callback);
            if (!result)
            {
                goto exit;
            }

            File.Delete(tmpwimcopy);

            //
            // Set the correct metadata on both images
            //
            image.NAME        = BootFirstImageName;
            image.DESCRIPTION = BootFirstImageName;
            image.FLAGS       = BootFirstImageFlag;
            if (image.WINDOWS.LANGUAGES == null)
            {
                image.WINDOWS.LANGUAGES = new WIMInformationXML.LANGUAGES()
                {
                    LANGUAGE = LanguageCode,
                    FALLBACK = new WIMInformationXML.FALLBACK()
                    {
                        LANGUAGE = LanguageCode,
                        Text     = "en-US"
                    },
                    DEFAULT = LanguageCode
                };
            }
            result = imagingInterface.SetWIMImageInformation(bootwim, 1, image);
            if (!result)
            {
                goto exit;
            }

            image.NAME        = BootSecondImageName;
            image.DESCRIPTION = BootSecondImageName;
            image.FLAGS       = BootSecondImageFlag;
            if (image.WINDOWS.LANGUAGES == null)
            {
                image.WINDOWS.LANGUAGES = new WIMInformationXML.LANGUAGES()
                {
                    LANGUAGE = LanguageCode,
                    FALLBACK = new WIMInformationXML.FALLBACK()
                    {
                        LANGUAGE = LanguageCode,
                        Text     = "en-US"
                    },
                    DEFAULT = LanguageCode
                };
            }
            result = imagingInterface.SetWIMImageInformation(bootwim, 2, image);
            if (!result)
            {
                goto exit;
            }

            //
            // Mark image as bootable
            //
            result = imagingInterface.MarkImageAsBootable(bootwim, 2);
            if (!result)
            {
                goto exit;
            }

            //
            // Modifying registry for each index
            //
            string tempSoftwareHiveBackup = Path.GetTempFileName();
            string tempSystemHiveBackup   = Path.GetTempFileName();

            result = imagingInterface.ExtractFileFromImage(bootwim, 1, Constants.SYSTEM_Hive_Location, tempSystemHiveBackup);
            if (!result)
            {
                goto exit;
            }

            result = imagingInterface.ExtractFileFromImage(bootwim, 1, Constants.SOFTWARE_Hive_Location, tempSoftwareHiveBackup);
            if (!result)
            {
                goto exit;
            }

            File.Copy(tempSoftwareHiveBackup, $"{tempSoftwareHiveBackup}.2");

            result = RegistryOperations.ModifyBootIndex2Registry($"{tempSoftwareHiveBackup}.2");
            if (!result)
            {
                goto exit;
            }

            result = imagingInterface.AddFileToImage(bootwim, 2, $"{tempSoftwareHiveBackup}.2", Constants.SOFTWARE_Hive_Location, progressCallback: callback);
            if (!result)
            {
                goto exit;
            }

            File.Delete($"{tempSoftwareHiveBackup}.2");

            result = RegistryOperations.ModifyBootIndex1Registry(tempSystemHiveBackup, tempSoftwareHiveBackup);
            if (!result)
            {
                goto exit;
            }

            result = imagingInterface.AddFileToImage(bootwim, 1, tempSystemHiveBackup, Constants.SYSTEM_Hive_Location, progressCallback: callback);
            if (!result)
            {
                goto exit;
            }

            result = imagingInterface.AddFileToImage(bootwim, 1, tempSoftwareHiveBackup, Constants.SOFTWARE_Hive_Location, progressCallback: callback);
            if (!result)
            {
                goto exit;
            }

            File.Delete(tempSoftwareHiveBackup);
            File.Delete(tempSystemHiveBackup);

            //
            // Adding missing files in index 2
            //
            progressCallback?.Invoke(Common.ProcessPhase.CreatingWindowsInstaller, true, 0, "Modifying assets for Setup PE (1)");
            result = imagingInterface.RenameFileInImage(bootwim, 2, Path.Combine("Windows", "System32", "winpe.jpg"), Path.Combine("Windows", "System32", "setup.bmp"), progressCallback: callback);
            if (!result)
            {
                goto exit;
            }

            progressCallback?.Invoke(Common.ProcessPhase.CreatingWindowsInstaller, true, 0, "Modifying assets for Setup PE (2)");
            var winpejpgtmp = Path.GetTempFileName();

            File.WriteAllBytes(winpejpgtmp, Constants.winpejpg);
            result = imagingInterface.AddFileToImage(bootwim, 2, winpejpgtmp, Path.Combine("Windows", "System32", "winpe.jpg"), progressCallback: callback);
            File.Delete(winpejpgtmp);
            if (!result)
            {
                goto exit;
            }

            progressCallback?.Invoke(Common.ProcessPhase.CreatingWindowsInstaller, true, 0, "Backporting missing files");

            var dirs = Directory.EnumerateDirectories(Path.Combine(MediaPath, "sources"), "??-??");

            if (dirs.Count() == 0)
            {
                dirs = Directory.EnumerateDirectories(Path.Combine(MediaPath, "sources"), "*-*");
            }
            string langcode = dirs.First().Replace(Path.Combine(MediaPath, "sources") + "\\", "");

            foreach (string file in Constants.SetupFilesToBackport)
            {
                string matchingfile              = Path.Combine(MediaPath, file).Replace("??-??", langcode);
                string normalizedPath            = file.Replace("??-??", langcode);
                string normalizedPathWithoutFile = normalizedPath.Contains("\\") ? string.Join("\\", normalizedPath.Split('\\').Reverse().Skip(1).Reverse()) : "";

                if (file == "sources\\background.bmp")
                {
                    string matchingfile1 = Path.Combine(MediaPath, "sources", "background_cli.bmp");
                    string matchingfile2 = Path.Combine(MediaPath, "sources", "background_srv.bmp");
                    if (File.Exists(matchingfile1))
                    {
                        result = imagingInterface.AddFileToImage(bootwim, 2, matchingfile1, normalizedPath, progressCallback: callback);
                        if (!result)
                        {
                            goto exit;
                        }
                    }
                    else if (File.Exists(matchingfile2))
                    {
                        result = imagingInterface.AddFileToImage(bootwim, 2, matchingfile2, normalizedPath, progressCallback: callback);
                        if (!result)
                        {
                            goto exit;
                        }
                    }
                }
                else if (File.Exists(matchingfile))
                {
                    result = imagingInterface.AddFileToImage(bootwim, 2, matchingfile, normalizedPath, progressCallback: callback);
                    if (!result)
                    {
                        goto exit;
                    }
                }
            }

            if (ulong.Parse(image.WINDOWS.VERSION.BUILD) >= 20231)
            {
                foreach (string file in Constants.SetupFilesToBackportStartingWith20231)
                {
                    string matchingfile              = Path.Combine(MediaPath, file).Replace("??-??", langcode);
                    string normalizedPath            = file.Replace("??-??", langcode);
                    string normalizedPathWithoutFile = normalizedPath.Contains("\\") ? string.Join("\\", normalizedPath.Split('\\').Reverse().Skip(1).Reverse()) : "";

                    if (file == "sources\\background.bmp")
                    {
                        string matchingfile1 = Path.Combine(MediaPath, "sources", "background_cli.bmp");
                        string matchingfile2 = Path.Combine(MediaPath, "sources", "background_srv.bmp");
                        if (File.Exists(matchingfile1))
                        {
                            result = imagingInterface.AddFileToImage(bootwim, 2, matchingfile1, normalizedPath, progressCallback: callback);
                            if (!result)
                            {
                                goto exit;
                            }
                        }
                        else if (File.Exists(matchingfile2))
                        {
                            result = imagingInterface.AddFileToImage(bootwim, 2, matchingfile2, normalizedPath, progressCallback: callback);
                            if (!result)
                            {
                                goto exit;
                            }
                        }
                    }
                    else if (File.Exists(matchingfile))
                    {
                        result = imagingInterface.AddFileToImage(bootwim, 2, matchingfile, normalizedPath, progressCallback: callback);
                        if (!result)
                        {
                            goto exit;
                        }
                    }
                }
            }

            //
            // We're done
            //

exit:
            return(result);
        }
Пример #8
0
 public void CreateFileTest(WimCompressionType compressionType)
 {
     using (WimHandle wimHandle = WimgApi.CreateFile(CreateWimPath, WimFileAccess.Write, WimCreationDisposition.CreateAlways, WimCreateFileOptions.None, compressionType))
     {
     }
 }
        public static bool CreateUpgradedEditionFromMountedImage(
            string MountedImagePath,
            string EditionID,
            string OutputInstallImage,
            bool IsVirtual,
            Common.CompressionType CompressionType,
            ProgressCallback progressCallback = null)
        {
            bool result = true;

            string SourceEdition = DismOperations.GetCurrentEdition(MountedImagePath);

            WIMInformationXML.WIM wiminfo;
            result = imagingInterface.GetWIMInformation(OutputInstallImage, out wiminfo);
            if (!result)
            {
                goto exit;
            }

            var srcimage = wiminfo.IMAGE.First(x => x.WINDOWS.EDITIONID.Equals(SourceEdition, StringComparison.InvariantCultureIgnoreCase));
            var index    = int.Parse(srcimage.INDEX);

            WimCompressionType compression = WimCompressionType.None;

            switch (CompressionType)
            {
            case Common.CompressionType.LZMS:
                compression = WimCompressionType.Lzms;
                break;

            case Common.CompressionType.LZX:
                compression = WimCompressionType.Lzx;
                break;

            case Common.CompressionType.XPRESS:
                compression = WimCompressionType.Xpress;
                break;
            }

            void callback(bool IsIndeterminate, int ProgressInPercentage, string SubOperation)
            {
                progressCallback?.Invoke(Common.ProcessPhase.ApplyingImage, IsIndeterminate, ProgressInPercentage, SubOperation);
            };

            DismOperations.SetTargetEdition(MountedImagePath, EditionID, callback);

            void callback2(string Operation, int ProgressPercentage, bool IsIndeterminate)
            {
                progressCallback?.Invoke(Common.ProcessPhase.CapturingImage, IsIndeterminate, ProgressPercentage, Operation);
            };

            string replaceStr  = LongestCommonSubstring(new string[] { srcimage.DISPLAYNAME, SourceEdition });
            string replaceStr2 = LongestCommonSubstring(new string[] { EditionID, SourceEdition });

            if (!string.IsNullOrEmpty(replaceStr2))
            {
                replaceStr2 = EditionID.Replace(replaceStr2, "");
            }
            else
            {
                replaceStr2 = EditionID;
            }

            string name;
            string description;
            string displayname;
            string displaydescription;

            if (string.IsNullOrEmpty(replaceStr))
            {
                name               = $"Windows 10 {replaceStr2}";
                description        = name;
                displayname        = name;
                displaydescription = name;
            }
            else
            {
                name               = srcimage.NAME.Replace(replaceStr, replaceStr2, StringComparison.InvariantCultureIgnoreCase);
                description        = srcimage.DESCRIPTION.Replace(replaceStr, replaceStr2, StringComparison.InvariantCultureIgnoreCase);
                displayname        = srcimage.DISPLAYNAME.Replace(replaceStr, replaceStr2, StringComparison.InvariantCultureIgnoreCase);
                displaydescription = srcimage.DISPLAYDESCRIPTION.Replace(replaceStr, replaceStr2, StringComparison.InvariantCultureIgnoreCase);
            }

            if (Constants.FriendlyEditionNames.Any(x => x.Key.Equals(EditionID, StringComparison.InvariantCultureIgnoreCase)))
            {
                name               = Constants.FriendlyEditionNames.First(x => x.Key.Equals(EditionID, StringComparison.InvariantCultureIgnoreCase)).Value;
                description        = name;
                displayname        = name;
                displaydescription = name;
            }

            result = imagingInterface.CaptureImage(
                OutputInstallImage,
                name,
                description,
                EditionID,
                MountedImagePath,
                displayname,
                displaydescription,
                compression,
                progressCallback: callback2,
                UpdateFrom: index);

            if (!result)
            {
                goto exit;
            }

            WIMInformationXML.IMAGE tmpImageInfo;
            result = imagingInterface.GetWIMImageInformation(OutputInstallImage, wiminfo.IMAGE.Count + 1, out tmpImageInfo);
            if (!result)
            {
                goto exit;
            }

            //
            // Set the correct metadata on the image
            //
            var sku = tmpImageInfo.WINDOWS.EDITIONID;

            tmpImageInfo.WINDOWS           = srcimage.WINDOWS;
            tmpImageInfo.WINDOWS.EDITIONID = sku;
            tmpImageInfo.FLAGS             = sku;

            if (tmpImageInfo.WINDOWS.INSTALLATIONTYPE.EndsWith(" Core", StringComparison.InvariantCultureIgnoreCase) && !tmpImageInfo.FLAGS.EndsWith("Core", StringComparison.InvariantCultureIgnoreCase))
            {
                tmpImageInfo.FLAGS += "Core";
            }

            tmpImageInfo.NAME               = name;
            tmpImageInfo.DESCRIPTION        = description;
            tmpImageInfo.DISPLAYNAME        = displayname;
            tmpImageInfo.DISPLAYDESCRIPTION = displaydescription;

            result = imagingInterface.SetWIMImageInformation(OutputInstallImage, wiminfo.IMAGE.Count + 1, tmpImageInfo);
            if (!result)
            {
                goto exit;
            }

            if (IsVirtual)
            {
                File.Delete(Path.Combine(MountedImagePath, "Windows", $"{EditionID}.xml"));
            }
            else
            {
                File.Delete(Path.Combine(MountedImagePath, "Windows", $"{SourceEdition}.xml"));
            }

exit:
            return(result);
        }
Пример #10
0
        /// <summary>
        /// Makes a new image file or opens an existing image file.
        /// </summary>
        /// <param name="path">The name of the file to create or to open.</param>
        /// <param name="desiredAccess">The type of <see cref="WimFileAccess"/> to the object. An application can obtain read access, write access, read/write access, or device query access.</param>
        /// <param name="creationDisposition">The <see cref="WimCreationDisposition"/> to take on files that exist, and which action to take when files do not exist.</param>
        /// <param name="options"><see cref="WimCreateFileOptions"/> to be used for the specified file.</param>
        /// <param name="compressionType">The <see cref="WimCompressionType"/> to be used for a newly created image file.  If the file already exists, then this value is ignored.</param>
        /// <returns>A <see cref="WimHandle"/> object representing the file.</returns>
        /// <exception cref="ArgumentNullException">path is null.</exception>
        /// <exception cref="Win32Exception">The Windows® Imaging API reported a failure.</exception>
        public static WimHandle CreateFile(string path, WimFileAccess desiredAccess, WimCreationDisposition creationDisposition, WimCreateFileOptions options, WimCompressionType compressionType)
        {
            // See if destinationFile is null
            if (path == null)
            {
                throw new ArgumentNullException(nameof(path));
            }

            // Call the native function
            WimHandle wimHandle = WimgApi.NativeMethods.WIMCreateFile(path, (DWORD)desiredAccess, (DWORD)creationDisposition, (DWORD)options, (DWORD)compressionType, out _);

            // See if the handle returned is valid
            if (wimHandle == null || wimHandle.IsInvalid)
            {
                // Throw a Win32Exception based on the last error code
                throw new Win32Exception();
            }

            // Return the handle to the wim
            return(wimHandle);
        }
Пример #11
0
        public bool CaptureImage(
            string wimFile,
            string imageName,
            string imageDescription,
            string imageFlag,
            string InputDirectory,
            string imageDisplayName                    = null,
            string imageDisplayDescription             = null,
            WimCompressionType compressionType         = WimCompressionType.Lzx,
            IImaging.ProgressCallback progressCallback = null,
            int UpdateFrom   = -1,
            bool PreserveACL = true)
        {
            string title = $"Creating {imageName} ({wimFile.Split('\\').Last()})";

            try
            {
                CallbackStatus ProgressCallback(ProgressMsg msg, object info, object progctx)
                {
                    switch (msg)
                    {
                    case ProgressMsg.ScanBegin:
                    {
                        ScanProgress m = (ScanProgress)info;
                        progressCallback?.Invoke($"Scanning files ({m.NumBytesScanned} bytes scanned, {m.NumDirsScanned} Directories, {m.NumNonDirsScanned} Files, Current directory: {m.CurPath})", 0, true);
                    }
                    break;

                    case ProgressMsg.ScanDEntry:
                    {
                        ScanProgress m = (ScanProgress)info;
                        progressCallback?.Invoke($"Scanning files ({m.NumBytesScanned} bytes scanned, {m.NumDirsScanned} Directories, {m.NumNonDirsScanned} Files, Current directory: {m.CurPath})", 0, true);
                    }
                    break;

                    case ProgressMsg.ScanEnd:
                    {
                        ScanProgress m = (ScanProgress)info;
                        progressCallback?.Invoke($"Scanning files ({m.NumBytesScanned} bytes scanned, {m.NumDirsScanned} Directories, {m.NumNonDirsScanned} Files, Current directory: {m.CurPath})", 0, true);
                    }
                    break;

                    case ProgressMsg.WriteMetadataBegin:
                        break;

                    case ProgressMsg.WriteStreams:
                    {
                        WriteStreamsProgress m = (WriteStreamsProgress)info;
                        progressCallback?.Invoke(title, (int)Math.Round((double)m.CompletedBytes / m.TotalBytes * 100), false);
                    }
                    break;

                    case ProgressMsg.WriteMetadataEnd:
                        break;
                    }
                    return(CallbackStatus.Continue);
                }

                if (File.Exists(wimFile))
                {
                    using (Wim wim = Wim.OpenWim(wimFile, OpenFlags.WriteAccess))
                    {
                        wim.RegisterCallback(ProgressCallback);
                        wim.AddImage(InputDirectory, imageName, null, PreserveACL ? AddFlags.StrictAcls : AddFlags.NoAcls);
                        if (!string.IsNullOrEmpty(imageDescription))
                        {
                            wim.SetImageDescription((int)wim.GetWimInfo().ImageCount, imageDescription);
                        }
                        if (!string.IsNullOrEmpty(imageDisplayName))
                        {
                            wim.SetImageProperty((int)wim.GetWimInfo().ImageCount, "DISPLAYNAME", imageDisplayName);
                        }
                        if (!string.IsNullOrEmpty(imageDisplayDescription))
                        {
                            wim.SetImageProperty((int)wim.GetWimInfo().ImageCount, "DISPLAYDESCRIPTION", imageDisplayDescription);
                        }
                        if (!string.IsNullOrEmpty(imageFlag))
                        {
                            wim.SetImageFlags((int)wim.GetWimInfo().ImageCount, imageFlag);
                        }
                        if (UpdateFrom != -1)
                        {
                            wim.ReferenceTemplateImage((int)wim.GetWimInfo().ImageCount, UpdateFrom);
                        }
                        wim.Overwrite(WriteFlags.None, Wim.DefaultThreads);
                    }
                }
                else
                {
                    var compression = CompressionType.None;
                    switch (compressionType)
                    {
                    case WimCompressionType.Lzms:
                    {
                        compression = CompressionType.LZMS;
                        break;
                    }

                    case WimCompressionType.Lzx:
                    {
                        compression = CompressionType.LZX;
                        break;
                    }

                    case WimCompressionType.None:
                    {
                        compression = CompressionType.None;
                        break;
                    }

                    case WimCompressionType.Xpress:
                    {
                        compression = CompressionType.XPRESS;
                        break;
                    }
                    }

                    using (Wim wim = Wim.CreateNewWim(compression))
                    {
                        wim.RegisterCallback(ProgressCallback);

                        string config = @"[ExclusionList]
\$ntfs.log
\hiberfil.sys
\pagefile.sys
\swapfile.sys
\System Volume Information";

                        var configpath = Path.GetTempFileName();
                        File.Delete(configpath);
                        File.WriteAllText(configpath, config);

                        wim.AddImage(InputDirectory, imageName, configpath, PreserveACL ? AddFlags.StrictAcls : AddFlags.NoAcls);
                        if (!string.IsNullOrEmpty(imageDescription))
                        {
                            wim.SetImageDescription((int)wim.GetWimInfo().ImageCount, imageDescription);
                        }
                        if (!string.IsNullOrEmpty(imageDisplayName))
                        {
                            wim.SetImageProperty((int)wim.GetWimInfo().ImageCount, "DISPLAYNAME", imageDisplayName);
                        }
                        if (!string.IsNullOrEmpty(imageDisplayDescription))
                        {
                            wim.SetImageProperty((int)wim.GetWimInfo().ImageCount, "DISPLAYDESCRIPTION", imageDisplayDescription);
                        }
                        if (!string.IsNullOrEmpty(imageFlag))
                        {
                            wim.SetImageFlags((int)wim.GetWimInfo().ImageCount, imageFlag);
                        }
                        wim.Write(wimFile, Wim.AllImages, WriteFlags.None, Wim.DefaultThreads);
                        File.Delete(configpath);
                    }
                }
            }
            catch (Exception ex)
            {
                return(false);
            }
            return(ReseatWIMXml(wimFile));
        }
Пример #12
0
        public bool ExportImage(string wimFile, string destinationWimFile, int imageIndex, IEnumerable <string> referenceWIMs = null, WimCompressionType compressionType = WimCompressionType.Lzx, IImaging.ProgressCallback progressCallback = null)
        {
            string title = $"Exporting {wimFile.Split('\\').Last()} - Index {imageIndex}";

            try
            {
                CallbackStatus ProgressCallback(ProgressMsg msg, object info, object progctx)
                {
                    switch (msg)
                    {
                    case ProgressMsg.WriteStreams:
                    {
                        WriteStreamsProgress m = (WriteStreamsProgress)info;
                        progressCallback?.Invoke(title, (int)Math.Round((double)m.CompletedBytes / m.TotalBytes * 100), false);
                    }
                    break;

                    case ProgressMsg.WriteMetadataBegin:
                        break;

                    case ProgressMsg.WriteMetadataEnd:
                        break;
                    }
                    return(CallbackStatus.Continue);
                }

                using (Wim srcWim = Wim.OpenWim(wimFile, OpenFlags.None))
                {
                    string imageName        = srcWim.GetImageName(imageIndex);
                    string imageDescription = srcWim.GetImageDescription(imageIndex);

                    var compression = CompressionType.None;
                    switch (compressionType)
                    {
                    case WimCompressionType.Lzms:
                    {
                        compression = CompressionType.LZMS;
                        break;
                    }

                    case WimCompressionType.Lzx:
                    {
                        compression = CompressionType.LZX;
                        break;
                    }

                    case WimCompressionType.None:
                    {
                        compression = CompressionType.None;
                        break;
                    }

                    case WimCompressionType.Xpress:
                    {
                        compression = CompressionType.XPRESS;
                        break;
                    }
                    }

                    if (referenceWIMs != null && referenceWIMs.Count() > 0)
                    {
                        srcWim.ReferenceResourceFiles(referenceWIMs, RefFlags.None, OpenFlags.None);
                    }

                    if (File.Exists(destinationWimFile))
                    {
                        using (Wim destWim = Wim.OpenWim(destinationWimFile, OpenFlags.WriteAccess))
                        {
                            destWim.RegisterCallback(ProgressCallback);

                            if (destWim.IsImageNameInUse(imageName))
                            {
                                srcWim.ExportImage(imageIndex, destWim, imageName + " " + DateTime.UtcNow.ToString(), imageDescription, ExportFlags.None);
                            }
                            else
                            {
                                srcWim.ExportImage(imageIndex, destWim, imageName, imageDescription, ExportFlags.None);
                            }

                            destWim.Overwrite(WriteFlags.None, Wim.DefaultThreads);
                        }
                    }
                    else
                    {
                        using (Wim destWim = Wim.CreateNewWim(compression))
                        {
                            destWim.RegisterCallback(ProgressCallback);
                            srcWim.ExportImage(imageIndex, destWim, imageName, imageDescription, ExportFlags.None);
                            destWim.Write(destinationWimFile, Wim.AllImages, compression == CompressionType.LZMS ? WriteFlags.Solid : WriteFlags.None, Wim.DefaultThreads);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                return(false);
            }
            return(ReseatWIMXml(destinationWimFile));
        }
Пример #13
0
        public static bool CreateBaseEdition(
            string UUPPath,
            string LanguageCode,
            string EditionID,
            string InputWindowsREPath,
            string OutputInstallImage,
            Common.CompressionType CompressionType,
            ProgressCallback progressCallback = null)
        {
            bool result = true;

            WimCompressionType compression = WimCompressionType.None;

            switch (CompressionType)
            {
            case Common.CompressionType.LZMS:
                compression = WimCompressionType.Lzms;
                break;

            case Common.CompressionType.LZX:
                compression = WimCompressionType.Lzx;
                break;

            case Common.CompressionType.XPRESS:
                compression = WimCompressionType.Xpress;
                break;
            }

            HashSet <string> ReferencePackages, referencePackagesToConvert;
            string           BaseESD = null;

            (result, BaseESD, ReferencePackages, referencePackagesToConvert) = FileLocator.LocateFilesForBaseEditionCreation(UUPPath, LanguageCode, EditionID, progressCallback);
            if (!result)
            {
                goto exit;
            }

            progressCallback?.Invoke(Common.ProcessPhase.PreparingFiles, true, 0, "Converting Reference Cabinets");

            int counter = 0;
            int total   = referencePackagesToConvert.Count;

            foreach (var file in referencePackagesToConvert)
            {
                int progressoffset = (int)Math.Round((double)counter / total * 100);
                int progressScale  = (int)Math.Round((double)1 / total * 100);

                string refesd = ConvertCABToESD(Path.Combine(UUPPath, file), progressCallback, progressoffset, progressScale);
                if (string.IsNullOrEmpty(refesd))
                {
                    progressCallback?.Invoke(Common.ProcessPhase.ReadingMetadata, true, 0, "Reference ESD creation from Cabinet files failed");
                    goto exit;
                }
                ReferencePackages.Add(refesd);
                counter++;
            }

            //
            // Gather information to transplant later into DisplayName and DisplayDescription
            //
            WIMInformationXML.IMAGE image;
            imagingInterface.GetWIMImageInformation(BaseESD, 3, out image);

            //
            // Export the install image
            //
            void callback(string Operation, int ProgressPercentage, bool IsIndeterminate)
            {
                progressCallback?.Invoke(Common.ProcessPhase.ApplyingImage, IsIndeterminate, ProgressPercentage, Operation);
            };

            result = imagingInterface.ExportImage(
                BaseESD,
                OutputInstallImage,
                3,
                referenceWIMs: ReferencePackages,
                compressionType: compression,
                progressCallback: callback);
            if (!result)
            {
                goto exit;
            }

            WIMInformationXML.WIM wim;
            imagingInterface.GetWIMInformation(OutputInstallImage, out wim);

            //
            // Set the correct metadata on the image
            //
            image.DISPLAYNAME        = image.NAME;
            image.DISPLAYDESCRIPTION = image.NAME;
            image.FLAGS = image.WINDOWS.EDITIONID;
            if (image.WINDOWS.LANGUAGES == null)
            {
                image.WINDOWS.LANGUAGES = new WIMInformationXML.LANGUAGES()
                {
                    LANGUAGE = LanguageCode,
                    FALLBACK = new WIMInformationXML.FALLBACK()
                    {
                        LANGUAGE = LanguageCode,
                        Text     = "en-US"
                    },
                    DEFAULT = LanguageCode
                };
            }
            result = imagingInterface.SetWIMImageInformation(OutputInstallImage, wim.IMAGE.Count, image);
            if (!result)
            {
                goto exit;
            }

            void callback2(string Operation, int ProgressPercentage, bool IsIndeterminate)
            {
                progressCallback?.Invoke(Common.ProcessPhase.IntegratingWinRE, IsIndeterminate, ProgressPercentage, Operation);
            };

            //
            // Integrate the WinRE image into the installation image
            //
            progressCallback?.Invoke(Common.ProcessPhase.IntegratingWinRE, true, 0, "");

            result = imagingInterface.AddFileToImage(
                OutputInstallImage,
                wim.IMAGE.Count,
                InputWindowsREPath,
                Path.Combine("Windows", "System32", "Recovery", "Winre.wim"),
                callback2);
            if (!result)
            {
                goto exit;
            }

exit:
            return(result);
        }
Пример #14
0
        public bool ExportImage(
            string wimFile,
            string destinationWimFile,
            int imageIndex,
            IEnumerable <string> referenceWIMs         = null,
            WimCompressionType compressionType         = WimCompressionType.Lzx,
            IImaging.ProgressCallback progressCallback = null)
        {
            return(WIMLibImaging.ExportImage(wimFile,
                                             destinationWimFile,
                                             imageIndex,
                                             referenceWIMs,
                                             compressionType,
                                             progressCallback));

            string title = $"Exporting {wimFile.Split('\\').Last()} - Index {imageIndex}";

            try
            {
                WimMessageResult callback2(WimMessageType messageType, object message, object userData)
                {
                    switch (messageType)
                    {
                    case WimMessageType.Progress:
                    {
                        WimMessageProgress progressMessage = (WimMessageProgress)message;
                        progressCallback?.Invoke($"{title} (Estimated time remaining: {progressMessage.EstimatedTimeRemaining})", progressMessage.PercentComplete, false);
                        break;
                    }
                    }

                    return(WimMessageResult.Success);
                }

                using (var wimHandle = WimgApi.CreateFile(
                           wimFile,
                           WimFileAccess.Read,
                           WimCreationDisposition.OpenExisting,
                           WimCreateFileOptions.Chunked,
                           WimCompressionType.None))
                {
                    // Always set a temporary path
                    //
                    WimgApi.SetTemporaryPath(wimHandle, Environment.GetEnvironmentVariable("TEMP"));

                    if (referenceWIMs != null)
                    {
                        foreach (var referenceFile in referenceWIMs)
                        {
                            WimgApi.SetReferenceFile(wimHandle, referenceFile, WimSetReferenceMode.Append, WimSetReferenceOptions.Chunked);
                        }
                    }

                    // Register a method to be called while actions are performed by WIMGAPi for this .wim file
                    //
                    WimgApi.RegisterMessageCallback(wimHandle, callback2);

                    using (var newWimHandle = WimgApi.CreateFile(
                               destinationWimFile,
                               WimFileAccess.Write,
                               WimCreationDisposition.OpenAlways,
                               compressionType == WimCompressionType.Lzms ? WimCreateFileOptions.Chunked : WimCreateFileOptions.None,
                               compressionType))
                    {
                        // Always set a temporary path
                        //
                        WimgApi.SetTemporaryPath(newWimHandle, Environment.GetEnvironmentVariable("TEMP"));

                        // Register a method to be called while actions are performed by WIMGAPi for this .wim file
                        //
                        WimgApi.RegisterMessageCallback(newWimHandle, callback2);

                        try
                        {
                            using (WimHandle imageHandle = WimgApi.LoadImage(wimHandle, imageIndex))
                            {
                                var    wiminfo      = WimgApi.GetImageInformationAsString(imageHandle);
                                var    wiminfoclass = WIMInformationXML.DeserializeIMAGE(wiminfo);
                                string imagename    = wiminfoclass.DISPLAYNAME == null ? wiminfoclass.NAME : wiminfoclass.DISPLAYNAME;

                                title = $"Exporting {imagename} ({wimFile.Split('\\').Last()} - Index {imageIndex})";

                                // Export the image contents
                                // This call is blocking but WIMGAPI will be calling MyCallbackMethod() during the process
                                //
                                WimgApi.ExportImage(imageHandle, newWimHandle, WimExportImageOptions.AllowDuplicates);
                            }
                        }
                        finally
                        {
                            // Be sure to unregister the callback method
                            //
                            WimgApi.UnregisterMessageCallback(wimHandle, callback2);

                            // Be sure to unregister the callback method
                            //
                            WimgApi.UnregisterMessageCallback(newWimHandle, callback2);
                        }
                    }
                }
            }
            catch
            {
                return(false);
            }
            return(true);
        }
Пример #15
0
        public bool CaptureImage(
            string wimFile,
            string imageName,
            string imageDescription,
            string imageFlag,
            string InputDirectory,
            string imageDisplayName                    = null,
            string imageDisplayDescription             = null,
            WIMInformationXML.WINDOWS windows          = null,
            WimCompressionType compressionType         = WimCompressionType.Lzx,
            WimCaptureImageOptions addFlags            = WimCaptureImageOptions.None,
            IImaging.ProgressCallback progressCallback = null)
        {
            string title = $"Creating {imageName} ({wimFile.Split('\\').Last()})";

            try
            {
                int directoriesScanned = 0;
                int filesScanned       = 0;

                WimMessageResult callback2(WimMessageType messageType, object message, object userData)
                {
                    switch (messageType)
                    {
                    case WimMessageType.Process:
                    {
                        WimMessageProcess processMessage = (WimMessageProcess)message;
                        if (processMessage.Path.StartsWith(Path.Combine(InputDirectory.EndsWith(":") ? InputDirectory + @"\" : InputDirectory, @"System Volume Information"), StringComparison.InvariantCultureIgnoreCase))
                        {
                            processMessage.Process = false;
                        }
                        break;
                    }

                    case WimMessageType.Progress:
                    {
                        WimMessageProgress progressMessage = (WimMessageProgress)message;
                        progressCallback?.Invoke($"{title} (Estimated time remaining: {progressMessage.EstimatedTimeRemaining})", progressMessage.PercentComplete, false);
                        break;
                    }

                    case WimMessageType.Scanning:
                    {
                        WimMessageScanning scanningMessage = (WimMessageScanning)message;

                        switch (scanningMessage.CountType)
                        {
                        case WimMessageScanningType.Directories:
                        {
                            directoriesScanned = scanningMessage.Count;
                            break;
                        }

                        case WimMessageScanningType.Files:
                        {
                            filesScanned = scanningMessage.Count;
                            break;
                        }
                        }

                        progressCallback?.Invoke($"Scanning objects ({filesScanned} files, {directoriesScanned} directories scanned)", 0, true);
                        break;
                    }
                    }

                    return(WimMessageResult.Success);
                }

                using (var wimHandle = WimgApi.CreateFile(
                           wimFile,
                           WimFileAccess.Write,
                           WimCreationDisposition.OpenAlways,
                           compressionType == WimCompressionType.Lzms ? WimCreateFileOptions.Chunked : WimCreateFileOptions.None,
                           compressionType))
                {
                    // Always set a temporary path
                    //
                    WimgApi.SetTemporaryPath(wimHandle, Environment.GetEnvironmentVariable("TEMP"));

                    // Register a method to be called while actions are performed by WIMGAPi for this .wim file
                    //
                    WimgApi.RegisterMessageCallback(wimHandle, callback2);

                    try
                    {
                        using (var imagehandle = WimgApi.CaptureImage(wimHandle, InputDirectory, addFlags))
                        {
                            var wiminfo      = WimgApi.GetImageInformationAsString(imagehandle);
                            var wiminfoclass = WIMInformationXML.DeserializeIMAGE(wiminfo);
                            if (!string.IsNullOrEmpty(imageFlag))
                            {
                                wiminfoclass.FLAGS = imageFlag;
                            }
                            if (!string.IsNullOrEmpty(imageName))
                            {
                                wiminfoclass.NAME = imageName;
                            }
                            if (!string.IsNullOrEmpty(imageDescription))
                            {
                                wiminfoclass.DESCRIPTION = imageDescription;
                            }
                            if (!string.IsNullOrEmpty(imageDisplayName))
                            {
                                wiminfoclass.DISPLAYNAME = imageDisplayName;
                            }
                            if (!string.IsNullOrEmpty(imageDisplayDescription))
                            {
                                wiminfoclass.DISPLAYDESCRIPTION = imageDisplayDescription;
                            }
                            if (windows != null)
                            {
                                wiminfoclass.WINDOWS = windows;
                            }

                            wiminfo = WIMInformationXML.SerializeIMAGE(wiminfoclass);
                            WimgApi.SetImageInformation(imagehandle, wiminfo);
                        }
                    }
                    finally
                    {
                        // Be sure to unregister the callback method
                        //
                        WimgApi.UnregisterMessageCallback(wimHandle, callback2);
                    }
                }
            }
            catch
            {
                return(false);
            }
            return(true);
        }