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 != 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 }
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); }
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); }