Example #1
0
        internal CabExtractor()
        {
            this.fdiAllocMemHandler    = new FDI.PFNALLOC(this.CabAllocMem);
            this.fdiFreeMemHandler     = new FDI.PFNFREE(this.CabFreeMem);
            this.fdiOpenStreamHandler  = new FDI.PFNOPEN(this.CabOpenStream);
            this.fdiReadStreamHandler  = new FDI.PFNREAD(this.CabReadStream);
            this.fdiWriteStreamHandler = new FDI.PFNWRITE(this.CabWriteStream);
            this.fdiCloseStreamHandler = new FDI.PFNCLOSE(this.CabCloseStream);
            this.fdiSeekStreamHandler  = new FDI.PFNSEEK(this.CabSeekStream);
            this.fdiNotifyHandler      = new FDI.PFNNOTIFY(this.CabExtractListNotify);

            this.cabStream   = null;
            this.cabNumbers  = new Hashtable(1);
            this.folderCount = 0;
            this.listFiles   = null;
            this.fdiHandle   = FDI.Create(this.fdiAllocMemHandler, this.fdiFreeMemHandler,
                                          this.fdiOpenStreamHandler, this.fdiReadStreamHandler, this.fdiWriteStreamHandler,
                                          this.fdiCloseStreamHandler, this.fdiSeekStreamHandler, FDI.CPU_80386, this.erf);
            if (this.erf.fError)
            {
                int error     = this.erf.erfOper;
                int errorCode = this.erf.erfType;
                this.erf.Dispose();
                this.erf       = null;
                this.fdiHandle = Pointer.Zero;
                throw new CabinetExtractException(error, errorCode, this.abortException);
            }
        }
Example #2
0
        internal bool IsCabinet(Stream cabStream, out ushort id, out int folderCount, out int fileCount)
        {
            Handle hStream = streamHandles.AllocHandle(cabStream);

            try
            {
                this.erf.Clear();
                FDI.CABINFO fdici;
                bool        isCabinet = 0 != FDI.IsCabinet(this.fdiHandle, hStream, out fdici);
                if (this.erf.fError && ((FDI.ERROR) this.erf.erfOper) == FDI.ERROR.UNKNOWN_CABINET_VERSION)
                {
                    this.erf.fError = false;
                    isCabinet       = false;
                }
                if (this.erf.fError)
                {
                    throw new CabinetExtractException(this.erf.erfOper, this.erf.erfType, this.abortException);
                }
                id          = fdici.setID;
                folderCount = (int)fdici.cFolders;
                fileCount   = (int)fdici.cFiles;
                return(isCabinet);
            }
            finally
            {
                streamHandles.FreeHandle(hStream);
            }
        }
Example #3
0
 internal void Process()
 {
     this.erf.Clear();
     FDI.Copy(this.fdiHandle, "", "", 0, this.fdiNotifyHandler, Pointer.Zero);
     if (this.erf.fError)
     {
         throw new CabinetExtractException(this.erf.erfOper, this.erf.erfType, this.abortException);
     }
 }
Example #4
0
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                // Dispose managed objects.
            }

            // Dispose unmanaged objects.
            if (this.fdiHandle != Pointer.Zero)
            {
                FDI.Destroy(this.fdiHandle);
                this.erf.Dispose();
                this.erf        = null;
                this.cabStream  = null;
                this.fileStream = null;
                this.fdiHandle  = Pointer.Zero;
            }
        }
Example #5
0
 /// <summary>
 /// Releases the handle by calling FDIDestroy().
 /// </summary>
 /// <returns>True if the release succeeded.</returns>
 protected override bool ReleaseHandle()
 {
     return(FDI.Destroy(this.handle));
 }
Example #6
0
        internal Handle CabExtractNotify(FDI.NOTIFICATIONTYPE notificationType, FDI.NOTIFICATION notification)
        {
            try
            {
                switch (notificationType)
                {
                case FDI.NOTIFICATIONTYPE.CABINET_INFO:
                {
                    this.nextCabinetName = (notification.psz1.Length != 0 ? notification.psz1 : null);
                    return((Handle)0);  // Continue
                }

                case FDI.NOTIFICATIONTYPE.PARTIAL_FILE:
                {
                    return((Handle)0);  // Continue
                }

                case FDI.NOTIFICATIONTYPE.NEXT_CABINET:
                {
                    this.cabNumbers[notification.psz1] = (short)notification.iCabinet;
                    return((Handle)0);  // Continue
                }

                case FDI.NOTIFICATIONTYPE.ENUMERATE:
                {
                    return((Handle)0);  // Continue
                }

                case FDI.NOTIFICATIONTYPE.COPY_FILE:
                {
                    if (notification.iFolder != this.folderId ||
                        (this.status.currentCabinetNumber == 0 && this.status.currentFileNumber == 0))
                    {
                        if (this.status.currentCabinetNumber != 0 || this.status.currentFileNumber != 0)
                        {
                                                        #if !CABMINIMAL
                            if (this.statusCallback != null)
                            {
                                this.status.statusType = CabinetStatusType.FinishFolder;
                                this.statusCallback(this.status, this.statusContext);
                            }
                                                        #endif // !CABMINIMAL
                            this.status.currentFolderNumber++;
                        }
                        this.folderId = notification.iFolder;
                                                #if !CABMINIMAL
                        if (this.statusCallback != null)
                        {
                            this.status.statusType = CabinetStatusType.StartFolder;
                            this.statusCallback(this.status, this.statusContext);
                        }
                                                #endif // !CABMINIMAL
                    }

                    bool utfName = (notification.attribs & (ushort)FileAttributes.Normal) != 0;  // _A_NAME_IS_UTF
                    //bool execute = (notification.attribs & (ushort) FileAttributes.Device) != 0;  // _A_EXEC

                    string name = notification.psz1;
                    if (utfName)
                    {
                        byte[] nameBytes = Encoding.Default.GetBytes(name);
                        name = Encoding.UTF8.GetString(nameBytes);
                    }
                    if ((this.filterFileHandler == null || this.filterFileHandler(this.status.currentFolderNumber, name, filterFileContext)) &&
                        this.openFileHandler != null)
                    {
                        this.status.currentFileName = name;

                                                #if !CABMINIMAL
                        if (this.statusCallback != null)
                        {
                            this.status.currentFileBytesProcessed = 0;
                            this.status.currentFileTotalBytes     = notification.cb;
                            this.status.statusType = CabinetStatusType.StartFile;
                            this.statusCallback(this.status, this.statusContext);
                        }
                                                #endif // !CABMINIMAL

                        DateTime lastWriteTime;
                        FDI.CabDateAndTimeToDateTime(notification.date, notification.time, out lastWriteTime);

                        Stream stream = this.openFileHandler(name, notification.cb, lastWriteTime, openFileContext);
                        if (stream != null)
                        {
                            Handle hStream = streamHandles.AllocHandle(stream);
                            return(hStream);
                        }
                        else
                        {
                                                        #if !CABMINIMAL
                            if (this.statusCallback != null)
                            {
                                this.status.fileBytesProcessed += notification.cb;
                                this.status.statusType          = CabinetStatusType.FinishFile;
                                this.statusCallback(this.status, this.statusContext);
                            }
                                                        #endif // !CABMINIMAL
                            this.status.currentFileName = null;
                            this.status.currentFileNumber++;
                        }
                    }
                    return((Handle)0);  // Continue
                }

                case FDI.NOTIFICATIONTYPE.CLOSE_FILE_INFO:
                {
                    Stream stream = (Stream)streamHandles[notification.hf];
                    streamHandles.FreeHandle(notification.hf);

                    bool utfName = (notification.attribs & (ushort)FileAttributes.Normal) != 0;  // _A_NAME_IS_UTF
                    //bool execute = (notification.attribs & (ushort) FileAttributes.Device) != 0;  // _A_EXEC

                    string name = notification.psz1;
                    if (utfName)
                    {
                        byte[] nameBytes = Encoding.Default.GetBytes(name);
                        name = Encoding.UTF8.GetString(nameBytes);
                    }
                    FileAttributes attributes = (FileAttributes)notification.attribs &
                                                (FileAttributes.Archive | FileAttributes.Hidden | FileAttributes.ReadOnly | FileAttributes.System);
                    if (attributes == (FileAttributes)0)
                    {
                        attributes = FileAttributes.Normal;
                    }
                    DateTime lastWriteTime;
                    FDI.CabDateAndTimeToDateTime(notification.date, notification.time, out lastWriteTime);
                    long length = notification.cb;

                    stream.Flush();
                    if (this.closeFileHandler != null)
                    {
                        this.closeFileHandler(name, stream, attributes, lastWriteTime, this.openFileContext);
                    }

                                        #if !CABMINIMAL
                    if (this.statusCallback != null)
                    {
                        long remainder = this.status.currentFileTotalBytes - this.status.currentFileBytesProcessed;
                        this.status.currentFileBytesProcessed += remainder;
                        this.status.fileBytesProcessed        += remainder;
                        this.status.statusType = CabinetStatusType.FinishFile;
                        this.statusCallback(this.status, this.statusContext);
                    }
                                        #endif // !CABMINIMAL
                    this.status.currentFileName = null;
                    this.status.currentFileNumber++;

                    return((Handle)1);                      // Continue
                }

                default:
                {
                    // Should never get any other notification types here.
                    throw new CabinetExtractException((int)FDI.ERROR.UNKNOWN_CABINET_VERSION, 0);
                }
                }
            }
            catch (Exception ex)
            {
                if (this.abortException == null)
                {
                    this.abortException = ex;
                }
                return((Handle)(-1));
            }
        }
Example #7
0
        internal Handle CabExtractListNotify(FDI.NOTIFICATIONTYPE notificationType, FDI.NOTIFICATION notification)
        {
            try
            {
                switch (notificationType)
                {
                case FDI.NOTIFICATIONTYPE.CABINET_INFO:
                {
                    this.nextCabinetName = (notification.psz1.Length != 0 ? notification.psz1 : null);
                    return((Handle)0);                     // Continue
                }

                case FDI.NOTIFICATIONTYPE.ENUMERATE:
                {
                    return((Handle)0);  // Continue
                }

                case FDI.NOTIFICATIONTYPE.PARTIAL_FILE:
                {
                    // This notification can occur when examining the contents of a non-first cab file.
                    return((Handle)0);  // Continue
                }

                case FDI.NOTIFICATIONTYPE.COPY_FILE:
                {
                    if (notification.iFolder != this.folderId || this.folderCount == 0)
                    {
                        this.folderId = notification.iFolder;
                        this.folderCount++;
                    }
                    bool utfName = (notification.attribs & (ushort)FileAttributes.Normal) != 0;  // _A_NAME_IS_UTF
                    //bool execute = (notification.attribs & (ushort) FileAttributes.Device) != 0;  // _A_EXEC

                    string name = notification.psz1;
                    if (utfName)
                    {
                        byte[] nameBytes = Encoding.Default.GetBytes(name);
                        name = Encoding.UTF8.GetString(nameBytes);
                    }
                    if (this.filterFileHandler == null || this.filterFileHandler(this.folderCount - 1, name, filterFileContext))
                    {
                        if (this.listFiles != null)
                        {
                                                        #if !CABMINIMAL
                            FileAttributes attributes = (FileAttributes)notification.attribs &
                                                        (FileAttributes.Archive | FileAttributes.Hidden | FileAttributes.ReadOnly | FileAttributes.System);
                            if (attributes == (FileAttributes)0)
                            {
                                attributes = FileAttributes.Normal;
                            }
                            DateTime lastWriteTime;
                            FDI.CabDateAndTimeToDateTime(notification.date, notification.time, out lastWriteTime);
                            long length = notification.cb;

                            CabinetFileInfo fileInfo = new CabinetFileInfo(Path.GetFileName(name),
                                                                           Path.GetDirectoryName(name), this.folderCount - 1, notification.iCabinet,
                                                                           attributes, lastWriteTime, length);
                            listFiles.Add(fileInfo);
                                                        #else
                            listFiles.Add(name);
                                                        #endif // CABMINIMAL
                        }
                    }
                    return((Handle)0);  // Continue
                }

                default:
                {
                    // Should never get any other notification types here.
                    throw new CabinetExtractException((int)FDI.ERROR.UNKNOWN_CABINET_VERSION, 0);
                }
                }
            }
            catch (Exception ex)
            {
                if (this.abortException == null)
                {
                    this.abortException = ex;
                }
                return((Handle)(-1));
            }
        }