Ejemplo n.º 1
0
        /// <summary>
        /// Allocates a decompressor for each cab and merges any cabs that need merged.
        /// </summary>
        /// <param name="cabinets"></param>
        /// <returns></returns>
        private static IEnumerable <MSCabinet> MergeCabs(IList <CabInfo> cabInfos)
        {
            /* Sometimes cab files are part of a set. We must merge those into their set before we leave here.
             * Otherwise extracting a file that extends beyond the bounds of one cab in the set will fail. This happens in VBRuntime.msi
             *
             * It can be determined if a cabinet has further parts to load by examining the mscabd_cabinet::flags field:
             * if (flags & MSCAB_HDR_PREVCAB) is non-zero, there is a predecessor cabinet to open() and prepend(). Its MS-DOS case-insensitive filename is mscabd_cabinet::prevname
             * if (flags & MSCAB_HDR_NEXTCAB) is non-zero, there is a successor cabinet to open() and append(). Its MS-DOS case-insensitive filename is mscabd_cabinet::nextname
             */
            var decompressors = new List <MSCabinet>();

            for (int i = 0; i < cabInfos.Count; i++)
            {
                CabInfo   cab   = cabInfos[i];
                MSCabinet msCab = null;
                try
                {
                    msCab = new MSCabinet(cab.LocalCabFile); // NOTE: Deliberately not disposing. Caller must cleanup.
                }
                catch (Exception)
                {
                    // As seen in https://github.com/activescott/lessmsi/issues/104, sometimes bogus cabs are inside of a msi but they're not needed to extract any files from. So we should attempt to ignore this failure here:
                    Debug.Fail(
                        string.Format("Cab name \"{0}\" could not be read by cab reader. Will attempt to ignore...", cab.CabSourceName)
                        );
                    continue;
                }

                if ((msCab.Flags & MSCabinetFlags.MSCAB_HDR_NEXTCAB) != 0)
                {
                    Debug.Assert(!string.IsNullOrEmpty(msCab.NextName), "Header indcates next cab but new cab not found.");
                    // load the cab found in NextName:
                    // Append it to msCab
                    Debug.Print("Found cabinet set. Nextname: " + msCab.NextName);
                    var nextCab   = FindCabAndRemoveFromList(cabInfos, msCab.NextName);
                    var msCabNext = new MSCabinet(nextCab.LocalCabFile);
                    msCab.Append(msCabNext);
                    decompressors.Add(msCab);
                }
                else if ((msCab.Flags & MSCabinetFlags.MSCAB_HDR_PREVCAB) != 0)
                {
                    Debug.Assert(!string.IsNullOrEmpty(msCab.PrevName), "Header indcates prev cab but new cab not found.");
                    Debug.Print("Found cabinet set. PrevName: " + msCab.PrevName);
                    var prevCabInfo = FindCabAndRemoveFromList(cabInfos, msCab.PrevName);
                    var msCabPrev   = new MSCabinet(prevCabInfo.LocalCabFile);
                    msCabPrev.Append(msCab);
                    decompressors.Add(msCabPrev);
                }
                else
                {                       // just a simple standalone cab
                    decompressors.Add(msCab);
                }
            }
            return(decompressors);
        }
Ejemplo n.º 2
0
        public void CabinetSet()
        {
            //NO WORKY!
            var root         = Path.Combine(AppPath, "cabinetset");
            var cabFilename1 = Path.Combine(root, "Disk1.CAB");
            var cabFilename2 = Path.Combine(root, "Disk2.CAB");

            using (var cab1 = new MSCabinet(cabFilename1))
                using (var cab2 = new MSCabinet(cabFilename2))
                {
                    cab1.Append(cab2);
                    ExplodeCab(cab1, OutDir(cabFilename1));
                }
            Console.ReadLine();
        }
Ejemplo n.º 3
0
        public void CabinetSet()
        {
            string root         = Path.Combine(AppContext.BaseDirectory, "test_files", "cabinetset");
            string cabFilename1 = Path.Combine(root, "Disk1.CAB");
            string cabFilename2 = Path.Combine(root, "Disk2.CAB");

            Assert.True(File.Exists(cabFilename1));
            Assert.True(File.Exists(cabFilename2));

            using (var cab1 = new MSCabinet(cabFilename1))
                using (var cab2 = new MSCabinet(cabFilename2))
                {
                    cab1.Append(cab2);
                    ExplodeCab(cab1, OutDir(cabFilename1));
                }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Allocates a decompressor for each cab and merges any cabs that need merged.
        /// </summary>
        /// <param name="cabinets"></param>
        /// <returns></returns>
        private static IEnumerable <MSCabinet> MergeCabs(IList <CabInfo> cabInfos)
        {
            /* Sometimes cab files are part of a set. We must merge those into their set before we leave here.
             * Otherwise extracting a file that extends beyond the bounds of one cab in the set will fail. This happens in VBRuntime.msi
             *
             * It can be determined if a cabinet has further parts to load by examining the mscabd_cabinet::flags field:
             * if (flags & MSCAB_HDR_PREVCAB) is non-zero, there is a predecessor cabinet to open() and prepend(). Its MS-DOS case-insensitive filename is mscabd_cabinet::prevname
             * if (flags & MSCAB_HDR_NEXTCAB) is non-zero, there is a successor cabinet to open() and append(). Its MS-DOS case-insensitive filename is mscabd_cabinet::nextname
             */
            var decompressors = new List <MSCabinet>();

            for (int i = 0; i < cabInfos.Count; i++)
            {
                CabInfo cab   = cabInfos[i];
                var     msCab = new MSCabinet(cab.LocalCabFile);            //NOTE: Deliberately not disposing. Caller must cleanup.

                if ((msCab.Flags & MSCabinetFlags.MSCAB_HDR_NEXTCAB) != 0)
                {
                    Debug.Assert(!string.IsNullOrEmpty(msCab.NextName), "Header indcates next cab but new cab not found.");
                    // load the cab found in NextName:
                    // Append it to msCab
                    Debug.Print("Found cabinet set. Nextname: " + msCab.NextName);
                    var nextCab   = FindCabAndRemoveFromList(cabInfos, msCab.NextName);
                    var msCabNext = new MSCabinet(nextCab.LocalCabFile);
                    msCab.Append(msCabNext);
                    decompressors.Add(msCab);
                }
                else if ((msCab.Flags & MSCabinetFlags.MSCAB_HDR_PREVCAB) != 0)
                {
                    Debug.Assert(!string.IsNullOrEmpty(msCab.PrevName), "Header indcates prev cab but new cab not found.");
                    Debug.Print("Found cabinet set. PrevName: " + msCab.PrevName);
                    var prevCabInfo = FindCabAndRemoveFromList(cabInfos, msCab.PrevName);
                    var msCabPrev   = new MSCabinet(prevCabInfo.LocalCabFile);
                    msCabPrev.Append(msCab);
                    decompressors.Add(msCabPrev);
                }
                else
                {                       // just a simple standalone cab
                    decompressors.Add(msCab);
                }
            }
            return(decompressors);
        }
Ejemplo n.º 5
0
        static void Main()
        {
            IEnumerable <string> files = Directory.GetFiles(AppPath, "*.cab");

            foreach (var f in files)
            {
                ExplodeCab(f);
            }

            //NO WORKY!
            var root         = Path.Combine(AppPath, "cabinetset");
            var cabFilename1 = Path.Combine(root, "Disk1.CAB");
            var cabFilename2 = Path.Combine(root, "Disk2.CAB");

            using (var cab1 = new MSCabinet(cabFilename1))
                using (var cab2 = new MSCabinet(cabFilename2))
                {
                    cab1.Append(cab2);
                    ExplodeCab(cab1, OutDir(cabFilename1));
                }
            Console.ReadLine();
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Allocates a decompressor for each cab and merges any cabs that need merged.
        /// </summary>
        /// <param name="cabinets"></param>
        /// <returns></returns>
        private static IEnumerable<MSCabinet> MergeCabs(IList<CabInfo> cabInfos)
        {
            /* Sometimes cab files are part of a set. We must merge those into their set before we leave here.
             * Otherwise extracting a file that extends beyond the bounds of one cab in the set will fail. This happens in VBRuntime.msi
             *
             * It can be determined if a cabinet has further parts to load by examining the mscabd_cabinet::flags field:
             * if (flags & MSCAB_HDR_PREVCAB) is non-zero, there is a predecessor cabinet to open() and prepend(). Its MS-DOS case-insensitive filename is mscabd_cabinet::prevname
             * if (flags & MSCAB_HDR_NEXTCAB) is non-zero, there is a successor cabinet to open() and append(). Its MS-DOS case-insensitive filename is mscabd_cabinet::nextname
             */
            var decompressors = new List<MSCabinet>();
            for (int i=0; i < cabInfos.Count; i++)
            {
                CabInfo cab = cabInfos[i];
                var msCab = new MSCabinet(cab.LocalCabFile);//NOTE: Deliberately not disposing. Caller must cleanup.

                if ((msCab.Flags & MSCabinetFlags.MSCAB_HDR_NEXTCAB) != 0)
                {
                    Debug.Assert(!string.IsNullOrEmpty(msCab.NextName), "Header indcates next cab but new cab not found.");
                    // load the cab found in NextName:
                    // Append it to msCab
                    Debug.Print("Found cabinet set. Nextname: " + msCab.NextName);
                    var nextCab = FindCabAndRemoveFromList(cabInfos, msCab.NextName);
                    var msCabNext = new MSCabinet(nextCab.LocalCabFile);
                    msCab.Append(msCabNext);
                    decompressors.Add(msCab);
                }
                else if ((msCab.Flags & MSCabinetFlags.MSCAB_HDR_PREVCAB) != 0)
                {
                    Debug.Assert(!string.IsNullOrEmpty(msCab.PrevName), "Header indcates prev cab but new cab not found.");
                    Debug.Print("Found cabinet set. PrevName: " + msCab.PrevName);
                    var prevCabInfo = FindCabAndRemoveFromList(cabInfos, msCab.PrevName);
                    var msCabPrev = new MSCabinet(prevCabInfo.LocalCabFile);
                    msCabPrev.Append(msCab);
                    decompressors.Add(msCabPrev);
                }
                else
                {	// just a simple standalone cab
                    decompressors.Add(msCab);
                }
            }
            return decompressors;
        }