Example #1
0
    private void PrepareOneMediaDiskForConsolidation(string mediaCab,
        InstallPathMap compressedFileMap, InstallPathMap uncompressedFileMap)
    {
        if(compressedFileMap.Count > 0)
        {
            string cabFile = null;
            if(mediaCab.StartsWith("#", StringComparison.Ordinal))
            {
                mediaCab = mediaCab.Substring(1);

                using (View streamView = this.OpenView("SELECT `Name`, `Data` FROM `_Streams` " +
                      "WHERE `Name` = '{0}'", mediaCab))
                {
                    streamView.Execute();
                    Record streamRec = streamView.Fetch();
                    if(streamRec == null)
                    {
                        this.LogMessage("Stream not found: {0}", mediaCab);
                        throw new InstallerException("Stream not found: " + mediaCab);
                    }
                    using(streamRec)
                    {
                        this.LogMessage("extract cab {0}", mediaCab);
                        cabFile = Path.Combine(this.TempDirectory,
                            Path.GetFileNameWithoutExtension(mediaCab) + ".cab");
                        streamRec.GetStream("Data", cabFile);
                    }
                }
            }
            else
            {
                cabFile = Path.Combine(this.SourceDirectory, mediaCab);
            }
            string[] fileKeys = new string[compressedFileMap.Keys.Count];
            compressedFileMap.Keys.CopyTo(fileKeys, 0);
            this.cabName = mediaCab;
            this.cabMsg = "extract {0}\\{1}";
            new CabInfo(cabFile).UnpackFiles(fileKeys, this.TempDirectory, fileKeys,
                this.CabinetProgress);
            ClearReadOnlyAttribute(this.TempDirectory, fileKeys);
        }
        foreach (KeyValuePair<string, InstallPath> entry in uncompressedFileMap)
        {
            string fileKey = (string) entry.Key;
            InstallPath fileInstallPath = (InstallPath) entry.Value;

            string filePath = Path.Combine(this.SourceDirectory, fileInstallPath.SourcePath);
            this.LogMessage("copy {0} {1}", filePath, fileKey);
            File.Copy(filePath, Path.Combine(this.TempDirectory, fileKey));
        }
    }
Example #2
0
    private void UpdateFilesOnOneMediaDisk(string mediaCab,
        InstallPathMap compressedFileMap, InstallPathMap uncompressedFileMap)
    {
        if(compressedFileMap.Count > 0)
        {
            string cabFile = null;
            bool cabFileIsTemp = false;
            if(mediaCab.StartsWith("#", StringComparison.Ordinal))
            {
                cabFileIsTemp = true;
                mediaCab = mediaCab.Substring(1);

                using(View streamView = this.OpenView("SELECT `Name`, `Data` FROM `_Streams` " +
                      "WHERE `Name` = '{0}'", mediaCab))
                {
                    streamView.Execute();
                    Record streamRec = streamView.Fetch();
                    if(streamRec == null)
                    {
                        this.LogMessage("Stream not found: {0}", mediaCab);
                        throw new InstallerException("Stream not found: " + mediaCab);
                    }
                    using(streamRec)
                    {
                        this.LogMessage("extract cab {0}", mediaCab);
                        Directory.CreateDirectory(this.TempDirectory);
                        cabFile = Path.Combine(this.TempDirectory,
                            Path.GetFileNameWithoutExtension(mediaCab) + ".cab");
                        streamRec.GetStream("Data", cabFile);
                    }
                }
            }
            else
            {
                cabFile = Path.Combine(this.SourceDirectory, mediaCab);
            }

            CabInfo cab = new CabInfo(cabFile);
            ArrayList fileKeyList = new ArrayList();
            foreach (CabFileInfo fileInCab in cab.GetFiles())
            {
                string fileKey = fileInCab.Name;
                if(this.Files[fileKey] != null)
                {
                    fileKeyList.Add(fileKey);
                }
            }
            string[] fileKeys = (string[]) fileKeyList.ToArray(typeof(string));

            Directory.CreateDirectory(this.TempDirectory);

            ArrayList remainingFileKeys = new ArrayList(fileKeys);
            foreach(string fileKey in fileKeys)
            {
                InstallPath fileInstallPath = compressedFileMap[fileKey];
                if(fileInstallPath != null)
                {
                    UpdateFileStats(fileKey, fileInstallPath);

                    string filePath = Path.Combine(this.WorkingDirectory, fileInstallPath.SourcePath);
                    this.LogMessage("copy {0} {1}", filePath, fileKey);
                    File.Copy(filePath, Path.Combine(this.TempDirectory, fileKey), true);
                    remainingFileKeys.Remove(fileKey);
                }
            }

            if(remainingFileKeys.Count > 0)
            {
                this.cabName = mediaCab;
                this.cabMsg = "extract {0}\\{1}";
                string[] remainingFileKeysArray = (string[]) remainingFileKeys.ToArray(typeof(string));
                cab.UnpackFiles(remainingFileKeysArray, this.TempDirectory, remainingFileKeysArray,
                    this.CabinetProgress);
            }

            ClearReadOnlyAttribute(this.TempDirectory, fileKeys);

            if(!cabFileIsTemp)
            {
                cab = new CabInfo(Path.Combine(this.WorkingDirectory, mediaCab));
            }
            this.cabName = mediaCab;
            this.cabMsg = "compress {0}\\{1}";
            cab.PackFiles(this.TempDirectory, fileKeys, fileKeys,
                this.CompressionLevel, this.CabinetProgress);

            if(cabFileIsTemp)
            {
                Record streamRec = new Record(1);
                streamRec.SetStream(1, cabFile);
                this.Execute(String.Format(
                    "UPDATE `_Streams` SET `Data` = ? WHERE `Name` = '{0}'", mediaCab),
                    streamRec);
            }
        }

        foreach (KeyValuePair<string, InstallPath> entry in uncompressedFileMap)
        {
            UpdateFileStats((string) entry.Key, (InstallPath) entry.Value);
        }
    }
Example #3
0
    private void ExtractFilesOnOneMediaDisk(string mediaCab,
        InstallPathMap compressedFileMap, InstallPathMap uncompressedFileMap)
    {
        if(compressedFileMap.Count > 0)
        {
            string cabFile = null;
            if(mediaCab.StartsWith("#", StringComparison.Ordinal))
            {
                mediaCab = mediaCab.Substring(1);

                using(View streamView = this.OpenView("SELECT `Name`, `Data` FROM `_Streams` " +
                      "WHERE `Name` = '{0}'", mediaCab))
                {
                    streamView.Execute();
                    Record streamRec = streamView.Fetch();
                    if(streamRec == null)
                    {
                        this.LogMessage("Stream not found: {0}", mediaCab);
                        throw new InstallerException("Stream not found: " + mediaCab);
                    }
                    using(streamRec)
                    {
                        this.LogMessage("extract cab {0}", mediaCab);
                        Directory.CreateDirectory(this.TempDirectory);
                        cabFile = Path.Combine(this.TempDirectory,
                            Path.GetFileNameWithoutExtension(mediaCab) + ".cab");
                        streamRec.GetStream("Data", cabFile);
                    }
                }
            }
            else
            {
                cabFile = Path.Combine(this.SourceDirectory, mediaCab);
            }

            this.cabName = mediaCab;
            this.cabMsg = "extract {0}\\{1} {2}";
            new CabInfo(cabFile).UnpackFileSet(compressedFileMap.SourcePaths, this.WorkingDirectory,
                this.CabinetProgress);
            ClearReadOnlyAttribute(this.WorkingDirectory, compressedFileMap.Values);
        }
        foreach(InstallPath fileInstallPath in uncompressedFileMap.Values)
        {
            string sourcePath = Path.Combine(this.SourceDirectory, fileInstallPath.SourcePath);
            string extractPath = Path.Combine(this.WorkingDirectory, fileInstallPath.SourcePath);
            if(Path.GetFullPath(sourcePath).ToLowerInvariant() !=
                Path.GetFullPath(extractPath).ToLowerInvariant())
            {
                if(!File.Exists(sourcePath))
                {
                    this.LogMessage("Error: Uncompressed file not found: {0}", sourcePath);
                    throw new FileNotFoundException("Uncompressed file not found.", sourcePath);
                }
                else
                {
                    this.LogMessage("copy {0} {1}", sourcePath, extractPath);
                    Directory.CreateDirectory(Path.GetDirectoryName(extractPath));
                    File.Copy(sourcePath, extractPath, true);
                }
            }
            else
            {
                if(!File.Exists(extractPath))
                {
                    this.LogMessage("Error: Uncompressed file not found: {0}", extractPath);
                    throw new FileNotFoundException("Uncompressed file not found.", extractPath);
                }
            }
        }
    }
Example #4
0
    private void ProcessFilesByMediaDisk(ICollection<string> fileKeys,
        ProcessFilesOnOneMediaDiskHandler diskHandler)
    {
        if(this.IsMergeModule())
        {
            InstallPathMap files = new InstallPathMap();
            foreach(string fileKey in this.Files.Keys)
            {
                if(fileKeys == null || fileKeys.Contains(fileKey))
                {
                    files[fileKey] = this.Files[fileKey];
                }
            }
            diskHandler("#MergeModule.CABinet", files, new InstallPathMap());
        }
        else
        {
            bool defaultCompressed = ((this.SummaryInfo.WordCount & 0x2) != 0);

            View fileView = null, mediaView = null;
            Record fileRec = null;
            try
            {
                fileView = this.OpenView("SELECT `File`, `Attributes`, `Sequence` " +
                    "FROM `File` ORDER BY `Sequence`");
                mediaView = this.OpenView("SELECT `DiskId`, `LastSequence`, `Cabinet` " +
                    "FROM `Media` ORDER BY `DiskId`");               
                fileView.Execute();
                mediaView.Execute();                

                int currentMediaDiskId = -1;
                int currentMediaMaxSequence = -1;
                string currentMediaCab = null;
                InstallPathMap compressedFileMap = new InstallPathMap();
                InstallPathMap uncompressedFileMap = new InstallPathMap();

                while((fileRec = fileView.Fetch()) != null)
                {
                    string fileKey = (string) fileRec[1];

                    if(fileKeys == null || fileKeys.Contains(fileKey))
                    {
                        int fileAttributes = fileRec.GetInteger(2);
                        int fileSequence = fileRec.GetInteger(3);

                        InstallPath fileInstallPath = this.Files[fileKey];
                        if(fileInstallPath == null)
                        {
                            this.LogMessage("Could not get install path for source file: {0}", fileKey);
                            throw new InstallerException("Could not get install path for source file: " + fileKey);
                        }

                        if(fileSequence > currentMediaMaxSequence)
                        {
                            if(currentMediaDiskId != -1)
                            {
                                diskHandler(currentMediaCab,
                                    compressedFileMap, uncompressedFileMap);
                                compressedFileMap.Clear();
                                uncompressedFileMap.Clear();
                            }

                            while(fileSequence > currentMediaMaxSequence)
                            {
                                Record mediaRec = mediaView.Fetch();
                                if(mediaRec == null)
                                {
                                    currentMediaDiskId = -1;
                                    break;
                                }
                                using(mediaRec)
                                {
                                    currentMediaDiskId = mediaRec.GetInteger(1);
                                    currentMediaMaxSequence = mediaRec.GetInteger(2);
                                    currentMediaCab = (string) mediaRec[3];
                                }
                            }
                            if(fileSequence > currentMediaMaxSequence) break;
                        }

                        if((fileAttributes & (int) Microsoft.Deployment.WindowsInstaller.FileAttributes.Compressed) != 0)
                        {
                            compressedFileMap[fileKey] = fileInstallPath;
                        }
                        else if ((fileAttributes & (int) Microsoft.Deployment.WindowsInstaller.FileAttributes.NonCompressed) != 0)
                        {
                            // Non-compressed files are located
                            // in the same directory as the MSI, without any path.
                            uncompressedFileMap[fileKey] = new InstallPath(fileInstallPath.SourceName);
                        }
                        else if(defaultCompressed)
                        {
                            compressedFileMap[fileKey] = fileInstallPath;
                        }
                        else
                        {
                            uncompressedFileMap[fileKey] = fileInstallPath;
                        }
                    }
                    fileRec.Close();
                    fileRec = null;
                }
                if(currentMediaDiskId != -1)
                {
                    diskHandler(currentMediaCab,
                        compressedFileMap, uncompressedFileMap);
                }
            }
            finally
            {
                if (fileRec != null) fileRec.Close();
                if (fileView != null) fileView.Close();
                if (mediaView != null) mediaView.Close();
            }
        }
    }
Example #5
0
 /// <summary>
 /// Rebuilds the cached directory structure information accessed by the
 /// <see cref="Directories"/> and <see cref="Files"/> properties. This
 /// should be done after modifying the File, Component, or Directory
 /// tables, or else the cached information may no longer be accurate.
 /// </summary>
 internal void UpdateDirectories()
 {
     this.dirPathMap = null;
     this.filePathMap = InstallPathMap.BuildFilePathMap(this,
     InstallPathMap.BuildComponentPathMap(this, this.Directories), false);
 }
Example #6
0
        public override SignatureVerificationResult VerifySignature(string path, string parent, string virtualPath)
        {
            SignatureVerificationResult svr = base.VerifySignature(path, parent, virtualPath);

            if (VerifyRecursive)
            {
                CreateDirectory(svr.TempPath);

                // TODO: Fix for MSIs with external CABs that are not present.
                using (var installPackage = new InstallPackage(svr.FullPath, DatabaseOpenMode.Transact, sourceDir: null, workingDir: svr.TempPath))
                {
                    InstallPathMap files         = installPackage.Files;
                    var            originalFiles = new Dictionary <string, string>();

                    // Flatten the files to avoid path too long errors. We use the File column and extension to create a unique file
                    // and record the original, relative MSI path in the result.
                    foreach (string key in installPackage.Files.Keys)
                    {
                        originalFiles[key] = installPackage.Files[key].TargetPath;
                        string name       = key + Path.GetExtension(installPackage.Files[key].TargetName);
                        string targetPath = Path.Combine(svr.TempPath, name);
                        installPackage.Files[key].TargetName = name;
                        installPackage.Files[key].SourceName = name;
                        installPackage.Files[key].SourcePath = targetPath;
                        installPackage.Files[key].TargetPath = targetPath;
                    }

                    try
                    {
                        Log.WriteMessage(LogVerbosity.Diagnostic, SignCheckResources.DiagExtractingFileContents, svr.TempPath);
                        installPackage.ExtractFiles(installPackage.Files.Keys);

                        foreach (string key in installPackage.Files.Keys)
                        {
                            SignatureVerificationResult packageFileResult = VerifyFile(installPackage.Files[key].TargetPath, svr.Filename, Path.Combine(svr.VirtualPath, originalFiles[key]), containerPath: null);
                            packageFileResult.AddDetail(DetailKeys.File, SignCheckResources.DetailFullName, originalFiles[key]);
                            svr.NestedResults.Add(packageFileResult);
                        }
                    }
                    catch (Exception e)
                    {
                        Log.WriteError(e.Message);
                    }
                }

                // Extract files from the Binary table - this is where items such as custom actions are stored.
                try
                {
                    using (var installDatabase = new Database(svr.FullPath, DatabaseOpenMode.ReadOnly))
                        using (View view = installDatabase.OpenView("SELECT `Name`, `Data` FROM `Binary`"))
                        {
                            view.Execute();

                            foreach (Record record in view)
                            {
                                string binaryFile     = (string)record["Name"];
                                string binaryFilePath = Path.Combine(svr.TempPath, binaryFile);
                                StructuredStorage.SaveStream(record, svr.TempPath);
                                SignatureVerificationResult binaryStreamResult = VerifyFile(binaryFilePath, svr.Filename, Path.Combine(svr.VirtualPath, binaryFile), containerPath: null);
                                binaryStreamResult.AddDetail(DetailKeys.Misc, SignCheckResources.FileExtractedFromBinaryTable);
                                svr.NestedResults.Add(binaryStreamResult);
                                record.Close();
                            }
                        }
                }
                catch (Exception e)
                {
                    Log.WriteError(e.Message);
                }

                DeleteDirectory(svr.TempPath);
            }

            return(svr);
        }