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)); } }
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); } }
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); } } } }
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(); } } }
/// <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); }
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); }