private int CabExtractCloseFile(NativeMethods.FDI.NOTIFICATION notification) { Stream stream = this.StreamHandles[notification.hf]; this.StreamHandles.FreeHandle(notification.hf); //bool execute = (notification.attribs & (ushort) FileAttributes.Device) != 0; // _A_EXEC string name = CabUnpacker.GetFileName(notification); FileAttributes attributes = (FileAttributes)notification.attribs & (FileAttributes.Archive | FileAttributes.Hidden | FileAttributes.ReadOnly | FileAttributes.System); if (attributes == (FileAttributes)0) { attributes = FileAttributes.Normal; } DateTime lastWriteTime; CompressionEngine.DosDateAndTimeToDateTime(notification.date, notification.time, out lastWriteTime); stream.Flush(); this.context.CloseFileWriteStream(name, stream, attributes, lastWriteTime); this.FileStream = null; long remainder = this.currentFileTotalBytes - this.currentFileBytesProcessed; this.currentFileBytesProcessed += remainder; this.fileBytesProcessed += remainder; this.OnProgress(ArchiveProgressType.FinishFile); this.currentFileName = null; return(1); // Continue }
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); }
private int CabExtractCopyFile(NativeMethods.FDI.NOTIFICATION notification) { if (notification.iFolder != this.folderId) { if (notification.iFolder != -3) // -3 is a special folderId used when continuing a folder from a previous cab { if (this.folderId != -1) // -1 means we just started the extraction sequence { this.currentFolderNumber++; } } this.folderId = notification.iFolder; } //bool execute = (notification.attribs & (ushort) FileAttributes.Device) != 0; // _A_EXEC string name = CabUnpacker.GetFileName(notification); if (this.filter == null || this.filter(name)) { this.currentFileNumber++; this.currentFileName = name; this.currentFileBytesProcessed = 0; this.currentFileTotalBytes = notification.cb; this.OnProgress(ArchiveProgressType.StartFile); DateTime lastWriteTime; CompressionEngine.DosDateAndTimeToDateTime(notification.date, notification.time, out lastWriteTime); Stream stream = this.context.OpenFileWriteStream(name, notification.cb, lastWriteTime); if (stream != null) { this.FileStream = stream; int streamHandle = this.StreamHandles.AllocHandle(stream); return(streamHandle); } else { this.fileBytesProcessed += notification.cb; this.OnProgress(ArchiveProgressType.FinishFile); this.currentFileName = null; } } return(0); // Continue }
private int CabExtractNotify(NativeMethods.FDI.NOTIFICATIONTYPE notificationType, NativeMethods.FDI.NOTIFICATION notification) { switch (notificationType) { case NativeMethods.FDI.NOTIFICATIONTYPE.CABINET_INFO: { if (this.NextCabinetName != null && this.NextCabinetName.StartsWith("?", StringComparison.Ordinal)) { // We are just continuing the copy of a file that spanned cabinets. // The next cabinet name needs to be preserved. this.NextCabinetName = this.NextCabinetName.Substring(1); } else { string nextCab = Marshal.PtrToStringAnsi(notification.psz1); this.NextCabinetName = (nextCab.Length != 0 ? nextCab : null); } return(0); // Continue } case NativeMethods.FDI.NOTIFICATIONTYPE.NEXT_CABINET: { string nextCab = Marshal.PtrToStringAnsi(notification.psz1); this.CabNumbers[nextCab] = (short)notification.iCabinet; this.NextCabinetName = "?" + this.NextCabinetName; return(0); // Continue } case NativeMethods.FDI.NOTIFICATIONTYPE.COPY_FILE: { return(this.CabExtractCopyFile(notification)); } case NativeMethods.FDI.NOTIFICATIONTYPE.CLOSE_FILE_INFO: { return(this.CabExtractCloseFile(notification)); } } return(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); this.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 = CabUnpacker.GetFileName(notification); if (this.filter == null || this.filter(name)) { if (this.fileList != null) { FileAttributes attributes = (FileAttributes)notification.attribs & (FileAttributes.Archive | FileAttributes.Hidden | FileAttributes.ReadOnly | FileAttributes.System); if (attributes == (FileAttributes)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); this.fileList.Add(fileInfo); this.currentFileNumber = this.fileList.Count - 1; this.fileBytesProcessed += notification.cb; } } this.totalFiles++; this.totalFileBytes += notification.cb; return(0); // Continue } } return(0); }