Exemple #1
0
        private static string GetFileName(NativeMethods.FDI.NOTIFICATION notification)
        {
            bool utf8Name = (notification.attribs & (ushort)FileAttributes.Normal) != 0;  // _A_NAME_IS_UTF

            // Non-utf8 names should be completely ASCII. But for compatibility with
            // legacy tools, interpret them using the current (Default) ANSI codepage.
            Encoding nameEncoding = utf8Name ? Encoding.UTF8 : Encoding.Default;

            // Find how many bytes are in the string.
            // Unfortunately there is no faster way.
            int nameBytesCount = 0;

            while (Marshal.ReadByte(notification.psz1, nameBytesCount) != 0)
            {
                nameBytesCount++;
            }

            byte[] nameBytes = new byte[nameBytesCount];
            Marshal.Copy(notification.psz1, nameBytes, 0, nameBytesCount);
            string name = nameEncoding.GetString(nameBytes);

            if (Path.IsPathRooted(name))
            {
                name = name.Replace("" + Path.VolumeSeparatorChar, "");
            }

            return(name);
        }
Exemple #2
0
        private int CabExtractCopyFile(NativeMethods.FDI.NOTIFICATION notification)
        {
            if (notification.iFolder != folderId)
            {
                if (notification.iFolder != -3) // -3 is a special folderId used when continuing a folder from a previous cab
                {
                    if (folderId != -1)         // -1 means we just started the extraction sequence
                    {
                        currentFolderNumber++;
                    }
                }

                folderId = notification.iFolder;
            }

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

            string name = GetFileName(notification);

            if (filter == null || filter(name))
            {
                currentFileNumber++;
                currentFileName = name;

                currentFileBytesProcessed = 0;
                currentFileTotalBytes     = notification.cb;
                OnProgress(ArchiveProgressType.StartFile);

                DateTime lastWriteTime;
                CompressionEngine.DosDateAndTimeToDateTime(notification.date, notification.time, out lastWriteTime);

                Stream stream = context.OpenFileWriteStream(name, notification.cb, lastWriteTime);
                if (stream != null)
                {
                    FileStream = stream;
                    int streamHandle = StreamHandles.AllocHandle(stream);
                    return(streamHandle);
                }

                fileBytesProcessed += notification.cb;
                OnProgress(ArchiveProgressType.FinishFile);
                currentFileName = null;
            }

            return(0); // Continue
        }
Exemple #3
0
        private int CabExtractNotify(NativeMethods.FDI.NOTIFICATIONTYPE notificationType, NativeMethods.FDI.NOTIFICATION notification)
        {
            switch (notificationType)
            {
            case NativeMethods.FDI.NOTIFICATIONTYPE.CABINET_INFO: {
                if (NextCabinetName != null && NextCabinetName.StartsWith("?", StringComparison.Ordinal))
                {
                    // We are just continuing the copy of a file that spanned cabinets.
                    // The next cabinet name needs to be preserved.
                    NextCabinetName = NextCabinetName.Substring(1);
                }
                else
                {
                    string nextCab = Marshal.PtrToStringAnsi(notification.psz1);
                    NextCabinetName = (nextCab.Length != 0 ? nextCab : null);
                }

                return(0);    // Continue
            }

            case NativeMethods.FDI.NOTIFICATIONTYPE.NEXT_CABINET: {
                string nextCab = Marshal.PtrToStringAnsi(notification.psz1);
                CabNumbers[nextCab] = notification.iCabinet;
                NextCabinetName     = "?" + NextCabinetName;
                return(0);    // Continue
            }

            case NativeMethods.FDI.NOTIFICATIONTYPE.COPY_FILE: {
                return(CabExtractCopyFile(notification));
            }

            case NativeMethods.FDI.NOTIFICATIONTYPE.CLOSE_FILE_INFO: {
                return(CabExtractCloseFile(notification));
            }
            }

            return(0);
        }
Exemple #4
0
        private int CabListNotify(NativeMethods.FDI.NOTIFICATIONTYPE notificationType, NativeMethods.FDI.NOTIFICATION notification)
        {
            switch (notificationType)
            {
            case NativeMethods.FDI.NOTIFICATIONTYPE.CABINET_INFO: {
                string nextCab = Marshal.PtrToStringAnsi(notification.psz1);
                NextCabinetName = (nextCab.Length != 0 ? nextCab : null);
                return(0);    // Continue
            }

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

            case NativeMethods.FDI.NOTIFICATIONTYPE.COPY_FILE: {
                //bool execute = (notification.attribs & (ushort) FileAttributes.Device) != 0;  // _A_EXEC

                string name = GetFileName(notification);

                if (filter == null || filter(name))
                {
                    if (fileList != null)
                    {
                        FileAttributes attributes = (FileAttributes)notification.attribs &
                                                    (FileAttributes.Archive | FileAttributes.Hidden | FileAttributes.ReadOnly | FileAttributes.System);
                        if (attributes == 0)
                        {
                            attributes = FileAttributes.Normal;
                        }

                        DateTime lastWriteTime;
                        CompressionEngine.DosDateAndTimeToDateTime(notification.date, notification.time, out lastWriteTime);
                        long length = notification.cb;

                        CabFileInfo fileInfo = new CabFileInfo(
                            name,
                            notification.iFolder,
                            notification.iCabinet,
                            attributes,
                            lastWriteTime,
                            length);
                        fileList.Add(fileInfo);
                        currentFileNumber   = fileList.Count - 1;
                        fileBytesProcessed += notification.cb;
                    }
                }

                totalFiles++;
                totalFileBytes += notification.cb;
                return(0);    // Continue
            }
            }

            return(0);
        }