예제 #1
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);
        }
예제 #2
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);
        }