mirror of
https://github.com/wabbajack-tools/wabbajack.git
synced 2024-08-30 18:42:17 +00:00
Initial commit
This commit is contained in:
parent
e099c7ae2e
commit
2d061bc1e4
9
.gitignore
vendored
9
.gitignore
vendored
@ -3,3 +3,12 @@
|
||||
################################################################################
|
||||
|
||||
/.vs/Wabbajack
|
||||
/BSA.Tools/bin/Debug/netstandard2.0
|
||||
/BSA.Tools/obj
|
||||
/packages
|
||||
/SevenZipExtractor/bin/Debug
|
||||
/SevenZipExtractor/obj/Debug
|
||||
/Wabbajack/bin/Debug
|
||||
/Wabbajack/obj/Debug
|
||||
/Wabbajack.Common/bin/Debug
|
||||
/Wabbajack.Common/obj/Debug
|
||||
|
409
BSA.Tools/Archive.cs
Normal file
409
BSA.Tools/Archive.cs
Normal file
@ -0,0 +1,409 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using static BSA.Tools.libbsarch;
|
||||
|
||||
namespace BSA.Tools
|
||||
{
|
||||
// Represents a BSA archive on disk (in READ mode)
|
||||
public class Archive : IDisposable
|
||||
{
|
||||
protected unsafe libbsarch.bsa_archive_t* _archive;
|
||||
|
||||
public UInt32 Version
|
||||
{
|
||||
get
|
||||
{
|
||||
lock(this) {
|
||||
unsafe
|
||||
{
|
||||
return libbsarch.bsa_version_get(_archive);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bsa_archive_type_t Type
|
||||
{
|
||||
get
|
||||
{
|
||||
lock(this)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return libbsarch.bsa_archive_type_get(_archive);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public UInt32 FileCount
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return libbsarch.bsa_file_count_get(_archive);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public UInt32 ArchiveFlags
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return libbsarch.bsa_archive_flags_get(_archive);
|
||||
}
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
libbsarch.bsa_archive_flags_set(_archive, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public UInt32 FileFlags
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return libbsarch.bsa_file_flags_get(_archive);
|
||||
}
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
libbsarch.bsa_file_flags_set(_archive, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool Compress
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return libbsarch.bsa_compress_get(_archive);
|
||||
}
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
libbsarch.bsa_compress_set(_archive, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool ShareData
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return libbsarch.bsa_share_data_get(_archive);
|
||||
}
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
libbsarch.bsa_share_data_set(_archive, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void Save()
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
check_err(libbsarch.bsa_save(_archive));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<ArchiveEntry> _entries = null;
|
||||
public IEnumerable<ArchiveEntry> Entries {
|
||||
get
|
||||
{
|
||||
if (_entries != null)
|
||||
return _entries;
|
||||
|
||||
return GetAndCacheEntries();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private IEnumerable<ArchiveEntry> GetAndCacheEntries()
|
||||
{
|
||||
var entries = new List<ArchiveEntry>();
|
||||
unsafe
|
||||
{
|
||||
foreach (var filename in GetFileNames())
|
||||
{
|
||||
entries.Add(new ArchiveEntry(this, _archive, filename));
|
||||
}
|
||||
}
|
||||
_entries = entries;
|
||||
return entries;
|
||||
}
|
||||
|
||||
public Archive()
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
_archive = libbsarch.bsa_create();
|
||||
}
|
||||
}
|
||||
|
||||
public void Create(string filename, bsa_archive_type_t type, EntryList entries)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
check_err(libbsarch.bsa_create_archive(_archive, filename, type, entries._list));
|
||||
}
|
||||
}
|
||||
|
||||
public Archive(string filename)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
_archive = libbsarch.bsa_create();
|
||||
check_err(libbsarch.bsa_load_from_file(_archive, filename));
|
||||
}
|
||||
}
|
||||
|
||||
public void AddFile(string filename, byte[] data)
|
||||
{
|
||||
lock(this)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
var ptr = Marshal.AllocHGlobal(data.Length);
|
||||
Marshal.Copy(data, 0, ptr, data.Length);
|
||||
libbsarch.bsa_add_file_from_memory(_archive, filename, (UInt32)data.Length, (byte*)ptr);
|
||||
Marshal.FreeHGlobal(ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
check_err(libbsarch.bsa_free(_archive));
|
||||
}
|
||||
}
|
||||
|
||||
public static void check_err(libbsarch.bsa_result_message_t bsa_result_message_t)
|
||||
{
|
||||
if (bsa_result_message_t.code != 0)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
int i = 0;
|
||||
for (i = 0; i < 1024 * 2; i += 2)
|
||||
if (bsa_result_message_t.text[i] == 0) break;
|
||||
|
||||
var msg = new String((sbyte*)bsa_result_message_t.text, 0, i, Encoding.Unicode);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<string> GetFileNames()
|
||||
{
|
||||
List<string> filenames = new List<string>();
|
||||
lock (this)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
check_err(libbsarch.bsa_iterate_files(_archive, (archive, filename, file, folder, context) =>
|
||||
{
|
||||
lock (filenames)
|
||||
{
|
||||
filenames.Add(filename);
|
||||
}
|
||||
return false;
|
||||
}, null));
|
||||
}
|
||||
}
|
||||
return filenames;
|
||||
}
|
||||
}
|
||||
|
||||
public class ArchiveEntry
|
||||
{
|
||||
private Archive _archive;
|
||||
private unsafe libbsarch.bsa_archive_t* _archivep;
|
||||
private string _filename;
|
||||
|
||||
public string Filename {
|
||||
get
|
||||
{
|
||||
return _filename;
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe ArchiveEntry(Archive archive, libbsarch.bsa_archive_t* archivep, string filename)
|
||||
{
|
||||
_archive = archive;
|
||||
_archivep = archivep;
|
||||
_filename = filename;
|
||||
}
|
||||
|
||||
public FileData GetFileData()
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
var result = libbsarch.bsa_extract_file_data_by_filename(_archivep, _filename);
|
||||
Archive.check_err(result.message);
|
||||
return new FileData(_archive, _archivep, result.buffer);
|
||||
}
|
||||
}
|
||||
|
||||
public void ExtractTo(Stream stream)
|
||||
{
|
||||
using (var data = GetFileData())
|
||||
{
|
||||
data.WriteTo(stream);
|
||||
}
|
||||
}
|
||||
|
||||
public void ExtractTo(string filename)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
libbsarch.bsa_extract_file(_archivep, _filename, filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class FileData : IDisposable
|
||||
{
|
||||
private Archive archive;
|
||||
private unsafe libbsarch.bsa_archive_t* archivep;
|
||||
private libbsarch.bsa_result_buffer_t result;
|
||||
|
||||
public unsafe FileData(Archive archive, libbsarch.bsa_archive_t* archivep, libbsarch.bsa_result_buffer_t result)
|
||||
{
|
||||
this.archive = archive;
|
||||
this.archivep = archivep;
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
public void WriteTo(Stream stream)
|
||||
{
|
||||
var memory = ToByteArray();
|
||||
stream.Write(memory, 0, (int)result.size);
|
||||
}
|
||||
|
||||
public byte[] ToByteArray()
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
byte[] memory = new byte[result.size];
|
||||
Marshal.Copy((IntPtr)result.data, memory, 0, (int)result.size);
|
||||
return memory;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
lock(archive)
|
||||
unsafe
|
||||
{
|
||||
Archive.check_err(libbsarch.bsa_file_data_free(archivep, result));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class EntryList : IDisposable
|
||||
{
|
||||
public unsafe bsa_entry_list_t* _list;
|
||||
|
||||
public EntryList()
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
_list = libbsarch.bsa_entry_list_create();
|
||||
}
|
||||
}
|
||||
|
||||
public UInt32 Count
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return libbsarch.bsa_entry_list_count(_list);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Add(string entry)
|
||||
{
|
||||
lock(this)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
libbsarch.bsa_entry_list_add(_list, entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
libbsarch.bsa_entry_list_free(_list);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
18
BSA.Tools/BSA.Tools.csproj
Normal file
18
BSA.Tools/BSA.Tools.csproj
Normal file
@ -0,0 +1,18 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="libbsarch.dll">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
18
BSA.Tools/Extensions.cs
Normal file
18
BSA.Tools/Extensions.cs
Normal file
@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace BSA.Tools
|
||||
{
|
||||
public static class Extensions
|
||||
{
|
||||
public static string ReadFourCC(this BinaryReader stream)
|
||||
{
|
||||
byte[] buf = new byte[4];
|
||||
stream.Read(buf, 0, 4);
|
||||
return new string(buf.Select(b => (char)b).ToArray());
|
||||
}
|
||||
}
|
||||
}
|
137
BSA.Tools/libbsarch.cs
Normal file
137
BSA.Tools/libbsarch.cs
Normal file
@ -0,0 +1,137 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace BSA.Tools
|
||||
{
|
||||
public class libbsarch
|
||||
{
|
||||
public struct bsa_archive_t { };
|
||||
public struct bsa_file_record_t { };
|
||||
public struct bsa_folder_record_t { };
|
||||
|
||||
public unsafe delegate bool bsa_file_iteration_proc_t(bsa_archive_t archive, [MarshalAs(UnmanagedType.LPWStr)] string file_path, bsa_file_record_t *file_record, bsa_folder_record_t *folder_record, void* context);
|
||||
|
||||
[DllImport("libbsarch.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern unsafe bsa_archive_t* bsa_create();
|
||||
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 1)]
|
||||
public struct bsa_result_message_t
|
||||
{
|
||||
public byte code; // bsa_result_code_t
|
||||
|
||||
public unsafe fixed byte text[1024 * 2];
|
||||
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 1)]
|
||||
public unsafe struct bsa_result_buffer_t
|
||||
{
|
||||
public UInt32 size;
|
||||
public IntPtr data;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 1)]
|
||||
public unsafe struct bsa_result_message_buffer_t
|
||||
{
|
||||
public bsa_result_buffer_t buffer;
|
||||
public bsa_result_message_t message;
|
||||
}
|
||||
|
||||
[DllImport("libbsarch.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern unsafe bsa_result_message_t bsa_free(bsa_archive_t* t);
|
||||
|
||||
[DllImport("libbsarch.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern unsafe bsa_result_message_t bsa_load_from_file(bsa_archive_t* archive, string file_path);
|
||||
|
||||
|
||||
[DllImport("libbsarch.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern unsafe UInt32 bsa_version_get(bsa_archive_t* archive);
|
||||
|
||||
|
||||
[DllImport("libbsarch.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern unsafe UInt32 bsa_file_count_get(bsa_archive_t* archive);
|
||||
|
||||
[DllImport("libbsarch.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern unsafe bsa_result_message_t bsa_iterate_files(bsa_archive_t *archive, bsa_file_iteration_proc_t file_iteration_proc, void* context);
|
||||
|
||||
[DllImport("libbsarch.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern unsafe bsa_result_message_buffer_t bsa_extract_file_data_by_filename(bsa_archive_t* archive, string file_path);
|
||||
|
||||
[DllImport("libbsarch.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern unsafe bsa_result_message_t bsa_extract_file(bsa_archive_t* archive, string file_path, string save_as);
|
||||
|
||||
[DllImport("libbsarch.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern unsafe bsa_result_message_t bsa_file_data_free(bsa_archive_t* archive, bsa_result_buffer_t file_data_result);
|
||||
|
||||
[DllImport("libbsarch.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern unsafe bsa_archive_type_t bsa_archive_type_get(bsa_archive_t* archive);
|
||||
|
||||
public enum bsa_archive_type_t : Int32
|
||||
{
|
||||
baNone, baTES3, baTES4, baFO3, baSSE, baFO4, baFO4dds
|
||||
}
|
||||
|
||||
[DllImport("libbsarch.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
|
||||
|
||||
public static extern unsafe bsa_result_message_t bsa_add_file_from_memory(bsa_archive_t* archive, string file_path, UInt32 size, byte* data);
|
||||
|
||||
[DllImport("libbsarch.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern unsafe bsa_result_message_t bsa_save(bsa_archive_t* archive);
|
||||
|
||||
[DllImport("libbsarch.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern unsafe bsa_result_message_t bsa_create_archive(bsa_archive_t* archive, string file_path, bsa_archive_type_t archive_type, bsa_entry_list_t* entry_list);
|
||||
|
||||
|
||||
// Entry Lists
|
||||
|
||||
public struct bsa_entry_list_t { }
|
||||
|
||||
[DllImport("libbsarch.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern unsafe bsa_entry_list_t* bsa_entry_list_create();
|
||||
|
||||
[DllImport("libbsarch.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern unsafe bsa_result_message_t bsa_entry_list_free(bsa_entry_list_t* entry_list);
|
||||
|
||||
[DllImport("libbsarch.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern unsafe UInt32 bsa_entry_list_count(bsa_entry_list_t* entry_list);
|
||||
|
||||
[DllImport("libbsarch.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern unsafe bsa_result_message_t bsa_entry_list_add(bsa_entry_list_t* entry_list, string entry_string);
|
||||
|
||||
[DllImport("libbsarch.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern unsafe UInt32 bsa_entry_list_get(bsa_entry_list_t* entry_list, UInt32 index, UInt32 string_buffer_size, string string_buffer);
|
||||
|
||||
|
||||
|
||||
[DllImport("libbsarch.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern unsafe UInt32 bsa_archive_flags_get(bsa_archive_t* archive);
|
||||
|
||||
[DllImport("libbsarch.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern unsafe void bsa_archive_flags_set(bsa_archive_t* archive, UInt32 flags);
|
||||
|
||||
[DllImport("libbsarch.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern unsafe UInt32 bsa_file_flags_get(bsa_archive_t* archive);
|
||||
|
||||
[DllImport("libbsarch.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern unsafe void bsa_file_flags_set(bsa_archive_t* archive, UInt32 flags);
|
||||
|
||||
[DllImport("libbsarch.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern unsafe bool bsa_compress_get(bsa_archive_t* archive);
|
||||
|
||||
[DllImport("libbsarch.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern unsafe void bsa_compress_set(bsa_archive_t* archive, bool flags);
|
||||
|
||||
[DllImport("libbsarch.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern unsafe bool bsa_share_data_get(bsa_archive_t* archive);
|
||||
|
||||
[DllImport("libbsarch.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
|
||||
public static extern unsafe void bsa_share_data_set(bsa_archive_t* archive, bool flags);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
BIN
BSA.Tools/libbsarch.dll
Normal file
BIN
BSA.Tools/libbsarch.dll
Normal file
Binary file not shown.
BIN
SevenZipExtractor/7zDll/x64/7z.dll
Normal file
BIN
SevenZipExtractor/7zDll/x64/7z.dll
Normal file
Binary file not shown.
BIN
SevenZipExtractor/7zDll/x86/7z.dll
Normal file
BIN
SevenZipExtractor/7zDll/x86/7z.dll
Normal file
Binary file not shown.
407
SevenZipExtractor/ArchiveFile.cs
Normal file
407
SevenZipExtractor/ArchiveFile.cs
Normal file
@ -0,0 +1,407 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace SevenZipExtractor
|
||||
{
|
||||
public class ArchiveFile : IDisposable
|
||||
{
|
||||
private SevenZipHandle sevenZipHandle;
|
||||
private readonly IInArchive archive;
|
||||
private readonly InStreamWrapper archiveStream;
|
||||
private IList<Entry> entries;
|
||||
|
||||
private string libraryFilePath;
|
||||
|
||||
public ArchiveFile(string archiveFilePath, string libraryFilePath = null)
|
||||
{
|
||||
this.libraryFilePath = libraryFilePath;
|
||||
|
||||
this.InitializeAndValidateLibrary();
|
||||
|
||||
if (!File.Exists(archiveFilePath))
|
||||
{
|
||||
throw new SevenZipException("Archive file not found");
|
||||
}
|
||||
|
||||
SevenZipFormat format;
|
||||
string extension = Path.GetExtension(archiveFilePath);
|
||||
|
||||
if (this.GuessFormatFromExtension(extension, out format))
|
||||
{
|
||||
// great
|
||||
}
|
||||
else if (this.GuessFormatFromSignature(archiveFilePath, out format))
|
||||
{
|
||||
// success
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new SevenZipException(Path.GetFileName(archiveFilePath) + " is not a known archive type");
|
||||
}
|
||||
|
||||
this.archive = this.sevenZipHandle.CreateInArchive(Formats.FormatGuidMapping[format]);
|
||||
this.archiveStream = new InStreamWrapper(File.OpenRead(archiveFilePath));
|
||||
}
|
||||
|
||||
public ArchiveFile(Stream archiveStream, SevenZipFormat? format = null, string libraryFilePath = null)
|
||||
{
|
||||
this.libraryFilePath = libraryFilePath;
|
||||
|
||||
this.InitializeAndValidateLibrary();
|
||||
|
||||
if (archiveStream == null)
|
||||
{
|
||||
throw new SevenZipException("archiveStream is null");
|
||||
}
|
||||
|
||||
if (format == null)
|
||||
{
|
||||
SevenZipFormat guessedFormat;
|
||||
|
||||
if (this.GuessFormatFromSignature(archiveStream, out guessedFormat))
|
||||
{
|
||||
format = guessedFormat;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new SevenZipException("Unable to guess format automatically");
|
||||
}
|
||||
}
|
||||
|
||||
this.archive = this.sevenZipHandle.CreateInArchive(Formats.FormatGuidMapping[format.Value]);
|
||||
this.archiveStream = new InStreamWrapper(archiveStream);
|
||||
}
|
||||
|
||||
public void Extract(string outputFolder, bool overwrite = false)
|
||||
{
|
||||
this.Extract(entry =>
|
||||
{
|
||||
string fileName = Path.Combine(outputFolder, entry.FileName);
|
||||
|
||||
if (entry.IsFolder)
|
||||
{
|
||||
return fileName;
|
||||
}
|
||||
|
||||
if (!File.Exists(fileName) || overwrite)
|
||||
{
|
||||
return fileName;
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
public void Extract(Func<Entry, Stream> getOutputStream, bool leave_open = false)
|
||||
{
|
||||
IList<Stream> fileStreams = new List<Stream>();
|
||||
|
||||
try
|
||||
{
|
||||
foreach (Entry entry in Entries)
|
||||
{
|
||||
Stream outputStream = getOutputStream(entry);
|
||||
|
||||
if (outputStream == null) // outputStream = null means SKIP
|
||||
{
|
||||
fileStreams.Add(null);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (entry.IsFolder)
|
||||
{
|
||||
fileStreams.Add(null);
|
||||
continue;
|
||||
}
|
||||
|
||||
fileStreams.Add(outputStream);
|
||||
}
|
||||
|
||||
this.archive.Extract(null, 0xFFFFFFFF, 0, new ArchiveStreamsCallback(fileStreams));
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (!leave_open)
|
||||
{
|
||||
foreach (Stream stream in fileStreams)
|
||||
{
|
||||
if (stream != null)
|
||||
{
|
||||
stream.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Extract(Func<Entry, string> getOutputPath)
|
||||
{
|
||||
IList<Stream> fileStreams = new List<Stream>();
|
||||
|
||||
try
|
||||
{
|
||||
foreach (Entry entry in Entries)
|
||||
{
|
||||
string outputPath = getOutputPath(entry);
|
||||
|
||||
if (outputPath == null) // getOutputPath = null means SKIP
|
||||
{
|
||||
fileStreams.Add(null);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (entry.IsFolder)
|
||||
{
|
||||
Directory.CreateDirectory(outputPath);
|
||||
fileStreams.Add(null);
|
||||
continue;
|
||||
}
|
||||
|
||||
string directoryName = Path.GetDirectoryName(outputPath);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(directoryName))
|
||||
{
|
||||
Directory.CreateDirectory(directoryName);
|
||||
}
|
||||
|
||||
fileStreams.Add(File.Create(outputPath));
|
||||
}
|
||||
|
||||
this.archive.Extract(null, 0xFFFFFFFF, 0, new ArchiveStreamsCallback(fileStreams));
|
||||
}
|
||||
finally
|
||||
{
|
||||
foreach (Stream stream in fileStreams)
|
||||
{
|
||||
if (stream != null)
|
||||
{
|
||||
stream.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IList<Entry> Entries
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.entries != null)
|
||||
{
|
||||
return this.entries;
|
||||
}
|
||||
|
||||
ulong checkPos = 32 * 1024;
|
||||
int open = this.archive.Open(this.archiveStream, ref checkPos, null);
|
||||
|
||||
if (open != 0)
|
||||
{
|
||||
throw new SevenZipException("Unable to open archive");
|
||||
}
|
||||
|
||||
uint itemsCount = this.archive.GetNumberOfItems();
|
||||
|
||||
this.entries = new List<Entry>();
|
||||
|
||||
for (uint fileIndex = 0; fileIndex < itemsCount; fileIndex++)
|
||||
{
|
||||
string fileName = this.GetProperty<string>(fileIndex, ItemPropId.kpidPath);
|
||||
bool isFolder = this.GetProperty<bool>(fileIndex, ItemPropId.kpidIsFolder);
|
||||
bool isEncrypted = this.GetProperty<bool>(fileIndex, ItemPropId.kpidEncrypted);
|
||||
ulong size = this.GetProperty<ulong>(fileIndex, ItemPropId.kpidSize);
|
||||
ulong packedSize = this.GetProperty<ulong>(fileIndex, ItemPropId.kpidPackedSize);
|
||||
DateTime creationTime = this.GetProperty<DateTime>(fileIndex, ItemPropId.kpidCreationTime);
|
||||
DateTime lastWriteTime = this.GetProperty<DateTime>(fileIndex, ItemPropId.kpidLastWriteTime);
|
||||
DateTime lastAccessTime = this.GetProperty<DateTime>(fileIndex, ItemPropId.kpidLastAccessTime);
|
||||
UInt32 crc = this.GetProperty<UInt32>(fileIndex, ItemPropId.kpidCRC);
|
||||
UInt32 attributes = this.GetProperty<UInt32>(fileIndex, ItemPropId.kpidAttributes);
|
||||
string comment = this.GetProperty<string>(fileIndex, ItemPropId.kpidComment);
|
||||
string hostOS = this.GetProperty<string>(fileIndex, ItemPropId.kpidHostOS);
|
||||
string method = this.GetProperty<string>(fileIndex, ItemPropId.kpidMethod);
|
||||
|
||||
bool isSplitBefore = this.GetProperty<bool>(fileIndex, ItemPropId.kpidSplitBefore);
|
||||
bool isSplitAfter = this.GetProperty<bool>(fileIndex, ItemPropId.kpidSplitAfter);
|
||||
|
||||
this.entries.Add(new Entry(this.archive, fileIndex)
|
||||
{
|
||||
FileName = fileName,
|
||||
IsFolder = isFolder,
|
||||
IsEncrypted = isEncrypted,
|
||||
Size = size,
|
||||
PackedSize = packedSize,
|
||||
CreationTime = creationTime,
|
||||
LastWriteTime = lastWriteTime,
|
||||
LastAccessTime = lastAccessTime,
|
||||
CRC = crc,
|
||||
Attributes = attributes,
|
||||
Comment = comment,
|
||||
HostOS = hostOS,
|
||||
Method = method,
|
||||
IsSplitBefore = isSplitBefore,
|
||||
IsSplitAfter = isSplitAfter
|
||||
});
|
||||
}
|
||||
|
||||
return this.entries;
|
||||
}
|
||||
}
|
||||
|
||||
private T GetProperty<T>(uint fileIndex, ItemPropId name)
|
||||
{
|
||||
PropVariant propVariant = new PropVariant();
|
||||
this.archive.GetProperty(fileIndex, name, ref propVariant);
|
||||
|
||||
T result = propVariant.VarType != VarEnum.VT_EMPTY
|
||||
? (T)(dynamic) propVariant.GetObject()
|
||||
: default(T);
|
||||
|
||||
propVariant.Clear();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void InitializeAndValidateLibrary()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(this.libraryFilePath))
|
||||
{
|
||||
string currentArchitecture = IntPtr.Size == 4 ? "x86" : "x64"; // magic check
|
||||
|
||||
if (File.Exists(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "7z-" + currentArchitecture + ".dll")))
|
||||
{
|
||||
this.libraryFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "7z-" + currentArchitecture + ".dll");
|
||||
}
|
||||
else if (File.Exists(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin", "7z-" + currentArchitecture + ".dll")))
|
||||
{
|
||||
this.libraryFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin", "7z-" + currentArchitecture + ".dll");
|
||||
}
|
||||
else if (File.Exists(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, currentArchitecture, "7z.dll")))
|
||||
{
|
||||
this.libraryFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, currentArchitecture, "7z.dll");
|
||||
}
|
||||
else if (File.Exists(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "7-Zip", "7z.dll")))
|
||||
{
|
||||
this.libraryFilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "7-Zip", "7z.dll");
|
||||
}
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(this.libraryFilePath))
|
||||
{
|
||||
throw new SevenZipException("libraryFilePath not set");
|
||||
}
|
||||
|
||||
if (!File.Exists(this.libraryFilePath))
|
||||
{
|
||||
throw new SevenZipException("7z.dll not found");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
this.sevenZipHandle = new SevenZipHandle(this.libraryFilePath);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new SevenZipException("Unable to initialize SevenZipHandle", e);
|
||||
}
|
||||
}
|
||||
|
||||
private bool GuessFormatFromExtension(string fileExtension, out SevenZipFormat format)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(fileExtension))
|
||||
{
|
||||
format = SevenZipFormat.Undefined;
|
||||
return false;
|
||||
}
|
||||
|
||||
fileExtension = fileExtension.TrimStart('.').Trim().ToLowerInvariant();
|
||||
|
||||
if (fileExtension.Equals("rar"))
|
||||
{
|
||||
// 7z has different GUID for Pre-RAR5 and RAR5, but they have both same extension (.rar)
|
||||
// If it is [0x52 0x61 0x72 0x21 0x1A 0x07 0x01 0x00] then file is RAR5 otherwise RAR.
|
||||
// https://www.rarlab.com/technote.htm
|
||||
|
||||
// We are unable to guess right format just by looking at extension and have to check signature
|
||||
|
||||
format = SevenZipFormat.Undefined;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Formats.ExtensionFormatMapping.ContainsKey(fileExtension))
|
||||
{
|
||||
format = SevenZipFormat.Undefined;
|
||||
return false;
|
||||
}
|
||||
|
||||
format = Formats.ExtensionFormatMapping[fileExtension];
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private bool GuessFormatFromSignature(string filePath, out SevenZipFormat format)
|
||||
{
|
||||
using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return GuessFormatFromSignature(fileStream, out format);
|
||||
}
|
||||
}
|
||||
|
||||
private bool GuessFormatFromSignature(Stream stream, out SevenZipFormat format)
|
||||
{
|
||||
int longestSignature = Formats.FileSignatures.Values.OrderByDescending(v => v.Length).First().Length;
|
||||
|
||||
byte[] archiveFileSignature = new byte[longestSignature];
|
||||
int bytesRead = stream.Read(archiveFileSignature, 0, longestSignature);
|
||||
|
||||
stream.Position -= bytesRead; // go back o beginning
|
||||
|
||||
if (bytesRead != longestSignature)
|
||||
{
|
||||
format = SevenZipFormat.Undefined;
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<SevenZipFormat, byte[]> pair in Formats.FileSignatures)
|
||||
{
|
||||
if (archiveFileSignature.Take(pair.Value.Length).SequenceEqual(pair.Value))
|
||||
{
|
||||
format = pair.Key;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
format = SevenZipFormat.Undefined;
|
||||
return false;
|
||||
}
|
||||
|
||||
~ArchiveFile()
|
||||
{
|
||||
this.Dispose(false);
|
||||
}
|
||||
|
||||
protected void Dispose(bool disposing)
|
||||
{
|
||||
if (this.archiveStream != null)
|
||||
{
|
||||
this.archiveStream.Dispose();
|
||||
}
|
||||
|
||||
if (this.archive != null)
|
||||
{
|
||||
Marshal.ReleaseComObject(this.archive);
|
||||
}
|
||||
|
||||
if (this.sevenZipHandle != null)
|
||||
{
|
||||
this.sevenZipHandle.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
this.Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
57
SevenZipExtractor/ArchiveFileCallback.cs
Normal file
57
SevenZipExtractor/ArchiveFileCallback.cs
Normal file
@ -0,0 +1,57 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace SevenZipExtractor
|
||||
{
|
||||
internal class ArchiveFileCallback : IArchiveExtractCallback
|
||||
{
|
||||
private readonly string fileName;
|
||||
private readonly uint fileNumber;
|
||||
private OutStreamWrapper fileStream; // to be removed
|
||||
|
||||
public ArchiveFileCallback(uint fileNumber, string fileName)
|
||||
{
|
||||
this.fileNumber = fileNumber;
|
||||
this.fileName = fileName;
|
||||
}
|
||||
|
||||
public void SetTotal(ulong total)
|
||||
{
|
||||
}
|
||||
|
||||
public void SetCompleted(ref ulong completeValue)
|
||||
{
|
||||
}
|
||||
|
||||
public int GetStream(uint index, out ISequentialOutStream outStream, AskMode askExtractMode)
|
||||
{
|
||||
if ((index != this.fileNumber) || (askExtractMode != AskMode.kExtract))
|
||||
{
|
||||
outStream = null;
|
||||
return 0;
|
||||
}
|
||||
|
||||
string fileDir = Path.GetDirectoryName(this.fileName);
|
||||
|
||||
if (!string.IsNullOrEmpty(fileDir))
|
||||
{
|
||||
Directory.CreateDirectory(fileDir);
|
||||
}
|
||||
|
||||
this.fileStream = new OutStreamWrapper(File.Create(this.fileName));
|
||||
|
||||
outStream = this.fileStream;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void PrepareOperation(AskMode askExtractMode)
|
||||
{
|
||||
}
|
||||
|
||||
public void SetOperationResult(OperationResult resultEOperationResult)
|
||||
{
|
||||
this.fileStream.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
45
SevenZipExtractor/ArchiveStreamCallback.cs
Normal file
45
SevenZipExtractor/ArchiveStreamCallback.cs
Normal file
@ -0,0 +1,45 @@
|
||||
using System.IO;
|
||||
|
||||
namespace SevenZipExtractor
|
||||
{
|
||||
internal class ArchiveStreamCallback : IArchiveExtractCallback
|
||||
{
|
||||
private readonly uint fileNumber;
|
||||
private readonly Stream stream;
|
||||
|
||||
public ArchiveStreamCallback(uint fileNumber, Stream stream)
|
||||
{
|
||||
this.fileNumber = fileNumber;
|
||||
this.stream = stream;
|
||||
}
|
||||
|
||||
public void SetTotal(ulong total)
|
||||
{
|
||||
}
|
||||
|
||||
public void SetCompleted(ref ulong completeValue)
|
||||
{
|
||||
}
|
||||
|
||||
public int GetStream(uint index, out ISequentialOutStream outStream, AskMode askExtractMode)
|
||||
{
|
||||
if ((index != this.fileNumber) || (askExtractMode != AskMode.kExtract))
|
||||
{
|
||||
outStream = null;
|
||||
return 0;
|
||||
}
|
||||
|
||||
outStream = new OutStreamWrapper(this.stream);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void PrepareOperation(AskMode askExtractMode)
|
||||
{
|
||||
}
|
||||
|
||||
public void SetOperationResult(OperationResult resultEOperationResult)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
58
SevenZipExtractor/ArchiveStreamsCallback.cs
Normal file
58
SevenZipExtractor/ArchiveStreamsCallback.cs
Normal file
@ -0,0 +1,58 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace SevenZipExtractor
|
||||
{
|
||||
internal class ArchiveStreamsCallback : IArchiveExtractCallback
|
||||
{
|
||||
private readonly IList<Stream> streams;
|
||||
|
||||
public ArchiveStreamsCallback(IList<Stream> streams)
|
||||
{
|
||||
this.streams = streams;
|
||||
}
|
||||
|
||||
public void SetTotal(ulong total)
|
||||
{
|
||||
}
|
||||
|
||||
public void SetCompleted(ref ulong completeValue)
|
||||
{
|
||||
}
|
||||
|
||||
public int GetStream(uint index, out ISequentialOutStream outStream, AskMode askExtractMode)
|
||||
{
|
||||
if (askExtractMode != AskMode.kExtract)
|
||||
{
|
||||
outStream = null;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (this.streams == null)
|
||||
{
|
||||
outStream = null;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Stream stream = this.streams[(int) index];
|
||||
|
||||
if (stream == null)
|
||||
{
|
||||
outStream = null;
|
||||
return 0;
|
||||
}
|
||||
|
||||
outStream = new OutStreamWrapper(stream);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void PrepareOperation(AskMode askExtractMode)
|
||||
{
|
||||
}
|
||||
|
||||
public void SetOperationResult(OperationResult resultEOperationResult)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
114
SevenZipExtractor/Entry.cs
Normal file
114
SevenZipExtractor/Entry.cs
Normal file
@ -0,0 +1,114 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace SevenZipExtractor
|
||||
{
|
||||
public class Entry
|
||||
{
|
||||
private readonly IInArchive archive;
|
||||
private readonly uint index;
|
||||
|
||||
internal Entry(IInArchive archive, uint index)
|
||||
{
|
||||
this.archive = archive;
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Name of the file with its relative path within the archive
|
||||
/// </summary>
|
||||
public string FileName { get; internal set; }
|
||||
/// <summary>
|
||||
/// True if entry is a folder, false if it is a file
|
||||
/// </summary>
|
||||
public bool IsFolder { get; internal set; }
|
||||
/// <summary>
|
||||
/// Original entry size
|
||||
/// </summary>
|
||||
public ulong Size { get; internal set; }
|
||||
/// <summary>
|
||||
/// Entry size in a archived state
|
||||
/// </summary>
|
||||
public ulong PackedSize { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Date and time of the file (entry) creation
|
||||
/// </summary>
|
||||
public DateTime CreationTime { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Date and time of the last change of the file (entry)
|
||||
/// </summary>
|
||||
public DateTime LastWriteTime { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Date and time of the last access of the file (entry)
|
||||
/// </summary>
|
||||
public DateTime LastAccessTime { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// CRC hash of the entry
|
||||
/// </summary>
|
||||
public UInt32 CRC { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Attributes of the entry
|
||||
/// </summary>
|
||||
public UInt32 Attributes { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// True if entry is encrypted, otherwise false
|
||||
/// </summary>
|
||||
public bool IsEncrypted { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Comment of the entry
|
||||
/// </summary>
|
||||
public string Comment { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Compression method of the entry
|
||||
/// </summary>
|
||||
public string Method { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Host operating system of the entry
|
||||
/// </summary>
|
||||
public string HostOS { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// True if there are parts of this file in previous split archive parts
|
||||
/// </summary>
|
||||
public bool IsSplitBefore { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// True if there are parts of this file in next split archive parts
|
||||
/// </summary>
|
||||
public bool IsSplitAfter { get; set; }
|
||||
|
||||
public void Extract(string fileName)
|
||||
{
|
||||
if (this.IsFolder)
|
||||
{
|
||||
Directory.CreateDirectory(fileName);
|
||||
return;
|
||||
}
|
||||
|
||||
string directoryName = Path.GetDirectoryName(fileName);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(directoryName))
|
||||
{
|
||||
Directory.CreateDirectory(directoryName);
|
||||
}
|
||||
|
||||
using (FileStream fileStream = File.Create(fileName))
|
||||
{
|
||||
this.Extract(fileStream);
|
||||
}
|
||||
}
|
||||
public void Extract(Stream stream)
|
||||
{
|
||||
this.archive.Extract(new[] { this.index }, 1, 0, new ArchiveStreamCallback(this.index, stream));
|
||||
}
|
||||
}
|
||||
}
|
112
SevenZipExtractor/Formats.cs
Normal file
112
SevenZipExtractor/Formats.cs
Normal file
@ -0,0 +1,112 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SevenZipExtractor
|
||||
{
|
||||
public class Formats
|
||||
{
|
||||
internal static readonly Dictionary<string, SevenZipFormat> ExtensionFormatMapping = new Dictionary<string, SevenZipFormat>
|
||||
{
|
||||
{"7z", SevenZipFormat.SevenZip},
|
||||
{"gz", SevenZipFormat.GZip},
|
||||
{"tar", SevenZipFormat.Tar},
|
||||
{"rar", SevenZipFormat.Rar},
|
||||
{"zip", SevenZipFormat.Zip},
|
||||
{"lzma", SevenZipFormat.Lzma},
|
||||
{"lzh", SevenZipFormat.Lzh},
|
||||
{"arj", SevenZipFormat.Arj},
|
||||
{"bz2", SevenZipFormat.BZip2},
|
||||
{"cab", SevenZipFormat.Cab},
|
||||
{"chm", SevenZipFormat.Chm},
|
||||
{"deb", SevenZipFormat.Deb},
|
||||
{"iso", SevenZipFormat.Iso},
|
||||
{"rpm", SevenZipFormat.Rpm},
|
||||
{"wim", SevenZipFormat.Wim},
|
||||
{"udf", SevenZipFormat.Udf},
|
||||
{"mub", SevenZipFormat.Mub},
|
||||
{"xar", SevenZipFormat.Xar},
|
||||
{"hfs", SevenZipFormat.Hfs},
|
||||
{"dmg", SevenZipFormat.Dmg},
|
||||
{"z", SevenZipFormat.Lzw},
|
||||
{"xz", SevenZipFormat.XZ},
|
||||
{"flv", SevenZipFormat.Flv},
|
||||
{"swf", SevenZipFormat.Swf},
|
||||
{"exe", SevenZipFormat.PE},
|
||||
{"dll", SevenZipFormat.PE},
|
||||
{"vhd", SevenZipFormat.Vhd}
|
||||
};
|
||||
|
||||
internal static Dictionary<SevenZipFormat, Guid> FormatGuidMapping = new Dictionary<SevenZipFormat, Guid>
|
||||
{
|
||||
{SevenZipFormat.SevenZip, new Guid("23170f69-40c1-278a-1000-000110070000")},
|
||||
{SevenZipFormat.Arj, new Guid("23170f69-40c1-278a-1000-000110040000")},
|
||||
{SevenZipFormat.BZip2, new Guid("23170f69-40c1-278a-1000-000110020000")},
|
||||
{SevenZipFormat.Cab, new Guid("23170f69-40c1-278a-1000-000110080000")},
|
||||
{SevenZipFormat.Chm, new Guid("23170f69-40c1-278a-1000-000110e90000")},
|
||||
{SevenZipFormat.Compound, new Guid("23170f69-40c1-278a-1000-000110e50000")},
|
||||
{SevenZipFormat.Cpio, new Guid("23170f69-40c1-278a-1000-000110ed0000")},
|
||||
{SevenZipFormat.Deb, new Guid("23170f69-40c1-278a-1000-000110ec0000")},
|
||||
{SevenZipFormat.GZip, new Guid("23170f69-40c1-278a-1000-000110ef0000")},
|
||||
{SevenZipFormat.Iso, new Guid("23170f69-40c1-278a-1000-000110e70000")},
|
||||
{SevenZipFormat.Lzh, new Guid("23170f69-40c1-278a-1000-000110060000")},
|
||||
{SevenZipFormat.Lzma, new Guid("23170f69-40c1-278a-1000-0001100a0000")},
|
||||
{SevenZipFormat.Nsis, new Guid("23170f69-40c1-278a-1000-000110090000")},
|
||||
{SevenZipFormat.Rar, new Guid("23170f69-40c1-278a-1000-000110030000")},
|
||||
{SevenZipFormat.Rar5, new Guid("23170f69-40c1-278a-1000-000110CC0000")},
|
||||
{SevenZipFormat.Rpm, new Guid("23170f69-40c1-278a-1000-000110eb0000")},
|
||||
{SevenZipFormat.Split, new Guid("23170f69-40c1-278a-1000-000110ea0000")},
|
||||
{SevenZipFormat.Tar, new Guid("23170f69-40c1-278a-1000-000110ee0000")},
|
||||
{SevenZipFormat.Wim, new Guid("23170f69-40c1-278a-1000-000110e60000")},
|
||||
{SevenZipFormat.Lzw, new Guid("23170f69-40c1-278a-1000-000110050000")},
|
||||
{SevenZipFormat.Zip, new Guid("23170f69-40c1-278a-1000-000110010000")},
|
||||
{SevenZipFormat.Udf, new Guid("23170f69-40c1-278a-1000-000110E00000")},
|
||||
{SevenZipFormat.Xar, new Guid("23170f69-40c1-278a-1000-000110E10000")},
|
||||
{SevenZipFormat.Mub, new Guid("23170f69-40c1-278a-1000-000110E20000")},
|
||||
{SevenZipFormat.Hfs, new Guid("23170f69-40c1-278a-1000-000110E30000")},
|
||||
{SevenZipFormat.Dmg, new Guid("23170f69-40c1-278a-1000-000110E40000")},
|
||||
{SevenZipFormat.XZ, new Guid("23170f69-40c1-278a-1000-0001100C0000")},
|
||||
{SevenZipFormat.Mslz, new Guid("23170f69-40c1-278a-1000-000110D50000")},
|
||||
{SevenZipFormat.PE, new Guid("23170f69-40c1-278a-1000-000110DD0000")},
|
||||
{SevenZipFormat.Elf, new Guid("23170f69-40c1-278a-1000-000110DE0000")},
|
||||
{SevenZipFormat.Swf, new Guid("23170f69-40c1-278a-1000-000110D70000")},
|
||||
{SevenZipFormat.Vhd, new Guid("23170f69-40c1-278a-1000-000110DC0000")},
|
||||
{SevenZipFormat.Flv, new Guid("23170f69-40c1-278a-1000-000110D60000")},
|
||||
{SevenZipFormat.SquashFS, new Guid("23170f69-40c1-278a-1000-000110D20000")},
|
||||
{SevenZipFormat.Lzma86, new Guid("23170f69-40c1-278a-1000-0001100B0000")},
|
||||
{SevenZipFormat.Ppmd, new Guid("23170f69-40c1-278a-1000-0001100D0000")},
|
||||
{SevenZipFormat.TE, new Guid("23170f69-40c1-278a-1000-000110CF0000")},
|
||||
{SevenZipFormat.UEFIc, new Guid("23170f69-40c1-278a-1000-000110D00000")},
|
||||
{SevenZipFormat.UEFIs, new Guid("23170f69-40c1-278a-1000-000110D10000")},
|
||||
{SevenZipFormat.CramFS, new Guid("23170f69-40c1-278a-1000-000110D30000")},
|
||||
{SevenZipFormat.APM, new Guid("23170f69-40c1-278a-1000-000110D40000")},
|
||||
{SevenZipFormat.Swfc, new Guid("23170f69-40c1-278a-1000-000110D80000")},
|
||||
{SevenZipFormat.Ntfs, new Guid("23170f69-40c1-278a-1000-000110D90000")},
|
||||
{SevenZipFormat.Fat, new Guid("23170f69-40c1-278a-1000-000110DA0000")},
|
||||
{SevenZipFormat.Mbr, new Guid("23170f69-40c1-278a-1000-000110DB0000")},
|
||||
{SevenZipFormat.MachO, new Guid("23170f69-40c1-278a-1000-000110DF0000")}
|
||||
};
|
||||
|
||||
internal static Dictionary<SevenZipFormat, byte[]> FileSignatures = new Dictionary<SevenZipFormat, byte[]>
|
||||
{
|
||||
{SevenZipFormat.Rar5, new byte[] {0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x01, 0x00}},
|
||||
{SevenZipFormat.Rar, new byte[] { 0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x00 }},
|
||||
{SevenZipFormat.Vhd, new byte[] { 0x63, 0x6F, 0x6E, 0x65, 0x63, 0x74, 0x69, 0x78 }},
|
||||
{SevenZipFormat.Deb, new byte[] { 0x21, 0x3C, 0x61, 0x72, 0x63, 0x68, 0x3E }},
|
||||
{SevenZipFormat.Dmg, new byte[] { 0x78, 0x01, 0x73, 0x0D, 0x62, 0x62, 0x60 }},
|
||||
{SevenZipFormat.SevenZip, new byte[] { 0x37, 0x7A, 0xBC, 0xAF, 0x27, 0x1C }},
|
||||
{SevenZipFormat.Tar, new byte[] { 0x75, 0x73, 0x74, 0x61, 0x72 }},
|
||||
{SevenZipFormat.Iso, new byte[] { 0x43, 0x44, 0x30, 0x30, 0x31 }},
|
||||
{SevenZipFormat.Cab, new byte[] { 0x4D, 0x53, 0x43, 0x46 }},
|
||||
{SevenZipFormat.Rpm, new byte[] { 0xed, 0xab, 0xee, 0xdb }},
|
||||
{SevenZipFormat.Xar, new byte[] { 0x78, 0x61, 0x72, 0x21 }},
|
||||
{SevenZipFormat.Chm, new byte[] { 0x49, 0x54, 0x53, 0x46 }},
|
||||
{SevenZipFormat.BZip2, new byte[] { 0x42, 0x5A, 0x68 }},
|
||||
{SevenZipFormat.Flv, new byte[] { 0x46, 0x4C, 0x56 }},
|
||||
{SevenZipFormat.Swf, new byte[] { 0x46, 0x57, 0x53 }},
|
||||
{SevenZipFormat.GZip, new byte[] { 0x1f, 0x0b }},
|
||||
{SevenZipFormat.Zip, new byte[] { 0x50, 0x4b }},
|
||||
{SevenZipFormat.Arj, new byte[] { 0x60, 0xEA }},
|
||||
{SevenZipFormat.Lzh, new byte[] { 0x2D, 0x6C, 0x68 }}
|
||||
};
|
||||
}
|
||||
}
|
23
SevenZipExtractor/IArchiveExtractCallback.cs
Normal file
23
SevenZipExtractor/IArchiveExtractCallback.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace SevenZipExtractor
|
||||
{
|
||||
[ComImport]
|
||||
[Guid("23170F69-40C1-278A-0000-000600200000")]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
internal interface IArchiveExtractCallback //: IProgress
|
||||
{
|
||||
void SetTotal(ulong total);
|
||||
void SetCompleted([In] ref ulong completeValue);
|
||||
|
||||
[PreserveSig]
|
||||
int GetStream(
|
||||
uint index,
|
||||
[MarshalAs(UnmanagedType.Interface)] out ISequentialOutStream outStream,
|
||||
AskMode askExtractMode);
|
||||
// GetStream OUT: S_OK - OK, S_FALSE - skeep this file
|
||||
|
||||
void PrepareOperation(AskMode askExtractMode);
|
||||
void SetOperationResult(OperationResult resultEOperationResult);
|
||||
}
|
||||
}
|
20
SevenZipExtractor/Kernel32Dll.cs
Normal file
20
SevenZipExtractor/Kernel32Dll.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
|
||||
namespace SevenZipExtractor
|
||||
{
|
||||
internal static class Kernel32Dll
|
||||
{
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
||||
internal static extern SafeLibraryHandle LoadLibrary([MarshalAs(UnmanagedType.LPTStr)] string lpFileName);
|
||||
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
|
||||
internal static extern IntPtr GetProcAddress(SafeLibraryHandle hModule, [MarshalAs(UnmanagedType.LPStr)] string procName);
|
||||
|
||||
[SuppressUnmanagedCodeSecurity]
|
||||
[DllImport("kernel32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static extern bool FreeLibrary(IntPtr hModule);
|
||||
}
|
||||
}
|
36
SevenZipExtractor/Properties/AssemblyInfo.cs
Normal file
36
SevenZipExtractor/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("SevenZipWrapper")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("SevenZipWrapper")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2016")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("8aa97f58-5044-4bba-b8d9-a74b6947a660")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
21
SevenZipExtractor/SafeLibraryHandle.cs
Normal file
21
SevenZipExtractor/SafeLibraryHandle.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Runtime.ConstrainedExecution;
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
|
||||
namespace SevenZipExtractor
|
||||
{
|
||||
internal sealed class SafeLibraryHandle : SafeHandleZeroOrMinusOneIsInvalid
|
||||
{
|
||||
public SafeLibraryHandle() : base(true)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>Release library handle</summary>
|
||||
/// <returns>true if the handle was released</returns>
|
||||
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
|
||||
protected override bool ReleaseHandle()
|
||||
{
|
||||
return Kernel32Dll.FreeLibrary(this.handle);
|
||||
}
|
||||
}
|
||||
}
|
24
SevenZipExtractor/SevenZipException.cs
Normal file
24
SevenZipExtractor/SevenZipException.cs
Normal file
@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace SevenZipExtractor
|
||||
{
|
||||
public class SevenZipException : Exception
|
||||
{
|
||||
public SevenZipException()
|
||||
{
|
||||
}
|
||||
|
||||
public SevenZipException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public SevenZipException(string message, Exception innerException) : base(message, innerException)
|
||||
{
|
||||
}
|
||||
|
||||
protected SevenZipException(SerializationInfo info, StreamingContext context) : base(info, context)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
82
SevenZipExtractor/SevenZipExtractor.csproj
Normal file
82
SevenZipExtractor/SevenZipExtractor.csproj
Normal file
@ -0,0 +1,82 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{8AA97F58-5044-4BBA-B8D9-A74B6947A660}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>SevenZipExtractor</RootNamespace>
|
||||
<AssemblyName>SevenZipExtractor</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ArchiveFileCallback.cs" />
|
||||
<Compile Include="ArchiveStreamsCallback.cs" />
|
||||
<Compile Include="ArchiveStreamCallback.cs" />
|
||||
<Compile Include="Entry.cs" />
|
||||
<Compile Include="Formats.cs" />
|
||||
<Compile Include="Kernel32Dll.cs" />
|
||||
<Compile Include="SevenZipFormat.cs" />
|
||||
<Compile Include="ArchiveFile.cs" />
|
||||
<Compile Include="IArchiveExtractCallback.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="SafeLibraryHandle.cs" />
|
||||
<Compile Include="SevenZipException.cs" />
|
||||
<Compile Include="SevenZipHandle.cs" />
|
||||
<Compile Include="SevenZipInterface.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="SevenZipExtractor.nuspec">
|
||||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<!--
|
||||
<ItemGroup>
|
||||
<Content Include="7z-x64.dll">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="7z-x86.dll">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
-->
|
||||
<Import Project="$(MSBuildProjectDirectory)\SevenZipExtractor.targets" />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
21
SevenZipExtractor/SevenZipExtractor.nuspec
Normal file
21
SevenZipExtractor/SevenZipExtractor.nuspec
Normal file
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0"?>
|
||||
<package >
|
||||
<metadata>
|
||||
<id>SevenZipExtractor</id>
|
||||
<version>1.0.12</version>
|
||||
<title>SevenZipExtractor</title>
|
||||
<authors>Eugene Sichkar, Alexander Selishchev, @matortheeternal, Hajin Jang, Artem Tarasov, Jose Pineiro, Raphael Stoeckli</authors>
|
||||
<owners>Alexander Selishchev</owners>
|
||||
<projectUrl>https://github.com/adoconnection/SevenZipExtractor</projectUrl>
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<description>C# wrapper for 7z.dll (included)</description>
|
||||
<releaseNotes></releaseNotes>
|
||||
<copyright>Copyright 2018</copyright>
|
||||
<tags>7Zip APM Arj BZip2 Cab Chm Compound Cpio CramFS Deb Dll Dmg Exe Fat Flv GZip Hfs Iso Lzh Lzma Lzma86 Mach-O Mbr Mub Nsis Ntfs Ppmd Rar Rar5 Rpm Split SquashFS Swf Swfc Tar TE Udf UEFIc UEFIs Vhd Wim Xar XZ Z Zip</tags>
|
||||
</metadata>
|
||||
<files>
|
||||
<file src="7zDll\x86\7z.dll" target="build\7zDll\x86\" />
|
||||
<file src="7zDll\x64\7z.dll" target="build\7zDll\x64\" />
|
||||
<file src="SevenZipExtractor.targets" target="build\SevenZipExtractor.targets" />
|
||||
</files>
|
||||
</package>
|
107
SevenZipExtractor/SevenZipExtractor.targets
Normal file
107
SevenZipExtractor/SevenZipExtractor.targets
Normal file
@ -0,0 +1,107 @@
|
||||
<!--
|
||||
*
|
||||
* WARNING: This MSBuild file requires MSBuild 4.0 features.
|
||||
*
|
||||
* Based on System.Data.SQLite.Core.targets, written by Joe Mistachkin and David Archer.
|
||||
* Released to the public domain, use at your own risk!
|
||||
*
|
||||
-->
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<!--
|
||||
******************************************************************************
|
||||
** Load Per-User Settings **
|
||||
******************************************************************************
|
||||
-->
|
||||
|
||||
<!--
|
||||
Create "SevenZipExtractor.Dll.Exclude" file in project directory
|
||||
to disable copying precompiled zlib binaries.
|
||||
-->
|
||||
<PropertyGroup>
|
||||
<Exclude7zDll Condition="Exists('$(MSBuildProjectDirectory)\SevenZipExtractor.Dll.Exclude')">true</Exclude7zDll>
|
||||
</PropertyGroup>
|
||||
|
||||
<!--
|
||||
******************************************************************************
|
||||
** 7z.dll Library Build Items **
|
||||
******************************************************************************
|
||||
-->
|
||||
|
||||
<ItemGroup>
|
||||
<DllFiles Condition="'$(Exclude7zDll)' != 'true' And
|
||||
'$(MSBuildThisFileDirectory)' != '' And
|
||||
HasTrailingSlash('$(MSBuildThisFileDirectory)')"
|
||||
Include="$(MSBuildThisFileDirectory)7zDll\**\7z.dll" />
|
||||
</ItemGroup>
|
||||
|
||||
<!--
|
||||
******************************************************************************
|
||||
** 7z.dll Library Content Items **
|
||||
******************************************************************************
|
||||
-->
|
||||
|
||||
<ItemGroup Condition="'@(DllFiles)' != ''">
|
||||
<None Include="@(DllFiles)">
|
||||
<Link>%(RecursiveDir)%(FileName)%(Extension)</Link>
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<!--
|
||||
******************************************************************************
|
||||
** 7z.dll Library Build Targets **
|
||||
******************************************************************************
|
||||
-->
|
||||
|
||||
<Target Name="CopyDllFiles"
|
||||
Condition="'$(CopyDllFiles)' != 'false' And
|
||||
'$(OutDir)' != '' And
|
||||
HasTrailingSlash('$(OutDir)') And
|
||||
Exists('$(OutDir)')"
|
||||
Inputs="@(DllFiles)"
|
||||
Outputs="@(DllFiles -> '$(OutDir)%(RecursiveDir)%(Filename)%(Extension)')">
|
||||
<!--
|
||||
NOTE: Copy "zlibwapi.dll" and all related files, for every
|
||||
architecture that we support, to the build output directory.
|
||||
-->
|
||||
<Copy SourceFiles="@(DllFiles)"
|
||||
DestinationFiles="@(DllFiles -> '$(OutDir)%(RecursiveDir)%(Filename)%(Extension)')" />
|
||||
</Target>
|
||||
|
||||
<!--
|
||||
******************************************************************************
|
||||
-->
|
||||
|
||||
<Target Name="CleanDllFiles"
|
||||
Condition="'$(CleanDllFiles)' != 'false' And
|
||||
'$(OutDir)' != '' And
|
||||
HasTrailingSlash('$(OutDir)') And
|
||||
Exists('$(OutDir)')">
|
||||
<!--
|
||||
NOTE: Delete "zlibwapi.dll" and all related files, for every
|
||||
architecture that we support, from the build output directory.
|
||||
-->
|
||||
<Delete Files="@(DllFiles -> '$(OutDir)%(RecursiveDir)%(Filename)%(Extension)')" />
|
||||
</Target>
|
||||
|
||||
<!--
|
||||
******************************************************************************
|
||||
** 7z.dll Library Build Properties **
|
||||
******************************************************************************
|
||||
-->
|
||||
|
||||
<PropertyGroup>
|
||||
<PostBuildEventDependsOn>
|
||||
$(PostBuildEventDependsOn);
|
||||
CopyDllFiles;
|
||||
</PostBuildEventDependsOn>
|
||||
<BuildDependsOn>
|
||||
$(BuildDependsOn);
|
||||
CopyDllFiles;
|
||||
</BuildDependsOn>
|
||||
<CleanDependsOn>
|
||||
$(CleanDependsOn);
|
||||
CleanDllFiles;
|
||||
</CleanDependsOn>
|
||||
</PropertyGroup>
|
||||
</Project>
|
285
SevenZipExtractor/SevenZipFormat.cs
Normal file
285
SevenZipExtractor/SevenZipFormat.cs
Normal file
@ -0,0 +1,285 @@
|
||||
namespace SevenZipExtractor
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public enum SevenZipFormat
|
||||
{
|
||||
// Default invalid format value
|
||||
Undefined = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Open 7-zip archive format.
|
||||
/// </summary>
|
||||
/// <remarks><a href="http://en.wikipedia.org/wiki/7-zip">Wikipedia information</a></remarks>
|
||||
SevenZip,
|
||||
|
||||
/// <summary>
|
||||
/// Proprietary Arj archive format.
|
||||
/// </summary>
|
||||
/// <remarks><a href="http://en.wikipedia.org/wiki/ARJ">Wikipedia information</a></remarks>
|
||||
Arj,
|
||||
|
||||
/// <summary>
|
||||
/// Open Bzip2 archive format.
|
||||
/// </summary>
|
||||
/// <remarks><a href="http://en.wikipedia.org/wiki/Bzip2">Wikipedia information</a></remarks>
|
||||
BZip2,
|
||||
|
||||
/// <summary>
|
||||
/// Microsoft cabinet archive format.
|
||||
/// </summary>
|
||||
/// <remarks><a href="http://en.wikipedia.org/wiki/Cabinet_(file_format)">Wikipedia information</a></remarks>
|
||||
Cab,
|
||||
|
||||
/// <summary>
|
||||
/// Microsoft Compiled HTML Help file format.
|
||||
/// </summary>
|
||||
/// <remarks><a href="http://en.wikipedia.org/wiki/Microsoft_Compiled_HTML_Help">Wikipedia information</a></remarks>
|
||||
Chm,
|
||||
|
||||
/// <summary>
|
||||
/// Microsoft Compound file format.
|
||||
/// </summary>
|
||||
/// <remarks><a href="http://en.wikipedia.org/wiki/Compound_File_Binary_Format">Wikipedia information</a></remarks>
|
||||
Compound,
|
||||
|
||||
/// <summary>
|
||||
/// Open Cpio archive format.
|
||||
/// </summary>
|
||||
/// <remarks><a href="http://en.wikipedia.org/wiki/Cpio">Wikipedia information</a></remarks>
|
||||
Cpio,
|
||||
|
||||
/// <summary>
|
||||
/// Open Debian software package format.
|
||||
/// </summary>
|
||||
/// <remarks><a href="http://en.wikipedia.org/wiki/Deb_(file_format)">Wikipedia information</a></remarks>
|
||||
Deb,
|
||||
|
||||
/// <summary>
|
||||
/// Open Gzip archive format.
|
||||
/// </summary>
|
||||
/// <remarks><a href="http://en.wikipedia.org/wiki/Gzip">Wikipedia information</a></remarks>
|
||||
GZip,
|
||||
|
||||
/// <summary>
|
||||
/// Open ISO disk image format.
|
||||
/// </summary>
|
||||
/// <remarks><a href="http://en.wikipedia.org/wiki/ISO_image">Wikipedia information</a></remarks>
|
||||
Iso,
|
||||
|
||||
/// <summary>
|
||||
/// Open Lzh archive format.
|
||||
/// </summary>
|
||||
/// <remarks><a href="http://en.wikipedia.org/wiki/Lzh">Wikipedia information</a></remarks>
|
||||
Lzh,
|
||||
|
||||
/// <summary>
|
||||
/// Open core 7-zip Lzma raw archive format.
|
||||
/// </summary>
|
||||
/// <remarks><a href="http://en.wikipedia.org/wiki/Lzma">Wikipedia information</a></remarks>
|
||||
Lzma,
|
||||
|
||||
/// <summary>
|
||||
/// Nullsoft installation package format.
|
||||
/// </summary>
|
||||
/// <remarks><a href="http://en.wikipedia.org/wiki/NSIS">Wikipedia information</a></remarks>
|
||||
Nsis,
|
||||
|
||||
/// <summary>
|
||||
/// RarLab Rar archive format.
|
||||
/// </summary>
|
||||
/// <remarks><a href="https://en.wikipedia.org/wiki/RAR_(file_format)">Wikipedia information</a></remarks>
|
||||
Rar,
|
||||
|
||||
/// <summary>
|
||||
/// RarLab Rar archive format, version 5.
|
||||
/// </summary>
|
||||
/// <remarks><a href="https://en.wikipedia.org/wiki/RAR_(file_format)">Wikipedia information</a></remarks>
|
||||
Rar5,
|
||||
|
||||
/// <summary>
|
||||
/// Open Rpm software package format.
|
||||
/// </summary>
|
||||
/// <remarks><a href="http://en.wikipedia.org/wiki/RPM_Package_Manager">Wikipedia information</a></remarks>
|
||||
Rpm,
|
||||
|
||||
/// <summary>
|
||||
/// Open split file format.
|
||||
/// </summary>
|
||||
/// <remarks><a href="?">Wikipedia information</a></remarks>
|
||||
Split,
|
||||
|
||||
/// <summary>
|
||||
/// Open Tar archive format.
|
||||
/// </summary>
|
||||
/// <remarks><a href="http://en.wikipedia.org/wiki/Tar_(file_format)">Wikipedia information</a></remarks>
|
||||
Tar,
|
||||
|
||||
/// <summary>
|
||||
/// Microsoft Windows Imaging disk image format.
|
||||
/// </summary>
|
||||
/// <remarks><a href="http://en.wikipedia.org/wiki/Windows_Imaging_Format">Wikipedia information</a></remarks>
|
||||
Wim,
|
||||
|
||||
/// <summary>
|
||||
/// Open LZW archive format; implemented in "compress" program; also known as "Z" archive format.
|
||||
/// </summary>
|
||||
/// <remarks><a href="http://en.wikipedia.org/wiki/Compress">Wikipedia information</a></remarks>
|
||||
Lzw,
|
||||
|
||||
/// <summary>
|
||||
/// Open Zip archive format.
|
||||
/// </summary>
|
||||
/// <remarks><a href="http://en.wikipedia.org/wiki/ZIP_(file_format)">Wikipedia information</a></remarks>
|
||||
Zip,
|
||||
|
||||
/// <summary>
|
||||
/// Open Udf disk image format.
|
||||
/// </summary>
|
||||
Udf,
|
||||
|
||||
/// <summary>
|
||||
/// Xar open source archive format.
|
||||
/// </summary>
|
||||
/// <remarks><a href="http://en.wikipedia.org/wiki/Xar_(archiver)">Wikipedia information</a></remarks>
|
||||
Xar,
|
||||
|
||||
/// <summary>
|
||||
/// Mub
|
||||
/// </summary>
|
||||
Mub,
|
||||
|
||||
/// <summary>
|
||||
/// Macintosh Disk Image on CD.
|
||||
/// </summary>
|
||||
/// <remarks><a href="http://en.wikipedia.org/wiki/HFS_Plus">Wikipedia information</a></remarks>
|
||||
Hfs,
|
||||
|
||||
/// <summary>
|
||||
/// Apple Mac OS X Disk Copy Disk Image format.
|
||||
/// </summary>
|
||||
Dmg,
|
||||
|
||||
/// <summary>
|
||||
/// Open Xz archive format.
|
||||
/// </summary>
|
||||
/// <remarks><a href="http://en.wikipedia.org/wiki/Xz">Wikipedia information</a></remarks>
|
||||
XZ,
|
||||
|
||||
/// <summary>
|
||||
/// MSLZ archive format.
|
||||
/// </summary>
|
||||
Mslz,
|
||||
|
||||
/// <summary>
|
||||
/// Flash video format.
|
||||
/// </summary>
|
||||
/// <remarks><a href="http://en.wikipedia.org/wiki/Flv">Wikipedia information</a></remarks>
|
||||
Flv,
|
||||
|
||||
/// <summary>
|
||||
/// Shockwave Flash format.
|
||||
/// </summary>
|
||||
/// <remarks><a href="http://en.wikipedia.org/wiki/Swf">Wikipedia information</a></remarks>
|
||||
Swf,
|
||||
|
||||
/// <summary>
|
||||
/// Windows PE executable format.
|
||||
/// </summary>
|
||||
/// <remarks><a href="http://en.wikipedia.org/wiki/Portable_Executable">Wikipedia information</a></remarks>
|
||||
PE,
|
||||
|
||||
/// <summary>
|
||||
/// Linux executable Elf format.
|
||||
/// </summary>
|
||||
/// <remarks><a href="http://en.wikipedia.org/wiki/Executable_and_Linkable_Format">Wikipedia information</a></remarks>
|
||||
Elf,
|
||||
|
||||
/// <summary>
|
||||
/// Windows Installer Database.
|
||||
/// </summary>
|
||||
/// <remarks><a href="http://en.wikipedia.org/wiki/Windows_Installer">Wikipedia information</a></remarks>
|
||||
Msi,
|
||||
|
||||
/// <summary>
|
||||
/// Microsoft virtual hard disk file format.
|
||||
/// </summary>
|
||||
/// <remarks><a href="http://en.wikipedia.org/wiki/VHD_%28file_format%29">Wikipedia information</a></remarks>
|
||||
Vhd,
|
||||
|
||||
/// <summary>
|
||||
/// SquashFS file system format.
|
||||
/// </summary>
|
||||
/// <remarks><a href="https://en.wikipedia.org/wiki/SquashFS">Wikipedia information</a></remarks>
|
||||
SquashFS,
|
||||
|
||||
/// <summary>
|
||||
/// Lzma86 file format.
|
||||
/// </summary>
|
||||
Lzma86,
|
||||
|
||||
/// <summary>
|
||||
/// Prediction by Partial Matching by Dmitry algorithm.
|
||||
/// </summary>
|
||||
/// <remarks><a href="https://en.wikipedia.org/wiki/Prediction_by_partial_matching">Wikipedia information</a></remarks>
|
||||
Ppmd,
|
||||
|
||||
/// <summary>
|
||||
/// TE format.
|
||||
/// </summary>
|
||||
TE,
|
||||
|
||||
/// <summary>
|
||||
/// UEFIc format.
|
||||
/// </summary>
|
||||
/// <remarks><a href="https://en.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface">Wikipedia information</a></remarks>
|
||||
UEFIc,
|
||||
|
||||
/// <summary>
|
||||
/// UEFIs format.
|
||||
/// </summary>
|
||||
/// <remarks><a href="https://en.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface">Wikipedia information</a></remarks>
|
||||
UEFIs,
|
||||
|
||||
/// <summary>
|
||||
/// Compressed ROM file system format.
|
||||
/// </summary>
|
||||
/// <remarks><a href="https://en.wikipedia.org/wiki/Cramfs">Wikipedia information</a></remarks>
|
||||
CramFS,
|
||||
|
||||
/// <summary>
|
||||
/// APM format.
|
||||
/// </summary>
|
||||
APM,
|
||||
|
||||
/// <summary>
|
||||
/// Swfc format.
|
||||
/// </summary>
|
||||
Swfc,
|
||||
|
||||
/// <summary>
|
||||
/// NTFS file system format.
|
||||
/// </summary>
|
||||
/// <remarks><a href="https://en.wikipedia.org/wiki/NTFS">Wikipedia information</a></remarks>
|
||||
Ntfs,
|
||||
|
||||
/// <summary>
|
||||
/// FAT file system format.
|
||||
/// </summary>
|
||||
/// <remarks><a href="https://en.wikipedia.org/wiki/File_Allocation_Table">Wikipedia information</a></remarks>
|
||||
Fat,
|
||||
|
||||
/// <summary>
|
||||
/// MBR format.
|
||||
/// </summary>
|
||||
/// <remarks><a href="https://en.wikipedia.org/wiki/Master_boot_record">Wikipedia information</a></remarks>
|
||||
Mbr,
|
||||
|
||||
/// <summary>
|
||||
/// Mach-O file format.
|
||||
/// </summary>
|
||||
/// <remarks><a href="https://en.wikipedia.org/wiki/Mach-O">Wikipedia information</a></remarks>
|
||||
MachO
|
||||
}
|
||||
}
|
68
SevenZipExtractor/SevenZipHandle.cs
Normal file
68
SevenZipExtractor/SevenZipHandle.cs
Normal file
@ -0,0 +1,68 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace SevenZipExtractor
|
||||
{
|
||||
internal class SevenZipHandle : IDisposable
|
||||
{
|
||||
private SafeLibraryHandle sevenZipSafeHandle;
|
||||
|
||||
public SevenZipHandle(string sevenZipLibPath)
|
||||
{
|
||||
this.sevenZipSafeHandle = Kernel32Dll.LoadLibrary(sevenZipLibPath);
|
||||
|
||||
if (this.sevenZipSafeHandle.IsInvalid)
|
||||
{
|
||||
throw new Win32Exception();
|
||||
}
|
||||
|
||||
IntPtr functionPtr = Kernel32Dll.GetProcAddress(this.sevenZipSafeHandle, "GetHandlerProperty");
|
||||
|
||||
// Not valid dll
|
||||
if (functionPtr == IntPtr.Zero)
|
||||
{
|
||||
this.sevenZipSafeHandle.Close();
|
||||
throw new ArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
~SevenZipHandle()
|
||||
{
|
||||
this.Dispose(false);
|
||||
}
|
||||
|
||||
protected void Dispose(bool disposing)
|
||||
{
|
||||
if ((this.sevenZipSafeHandle != null) && !this.sevenZipSafeHandle.IsClosed)
|
||||
{
|
||||
this.sevenZipSafeHandle.Close();
|
||||
}
|
||||
|
||||
this.sevenZipSafeHandle = null;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
this.Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
public IInArchive CreateInArchive(Guid classId)
|
||||
{
|
||||
if (this.sevenZipSafeHandle == null)
|
||||
{
|
||||
throw new ObjectDisposedException("SevenZipHandle");
|
||||
}
|
||||
|
||||
IntPtr procAddress = Kernel32Dll.GetProcAddress(this.sevenZipSafeHandle, "CreateObject");
|
||||
CreateObjectDelegate createObject = (CreateObjectDelegate) Marshal.GetDelegateForFunctionPointer(procAddress, typeof (CreateObjectDelegate));
|
||||
|
||||
object result;
|
||||
Guid interfaceId = typeof (IInArchive).GUID;
|
||||
createObject(ref classId, ref interfaceId, out result);
|
||||
|
||||
return result as IInArchive;
|
||||
}
|
||||
}
|
||||
}
|
529
SevenZipExtractor/SevenZipInterface.cs
Normal file
529
SevenZipExtractor/SevenZipInterface.cs
Normal file
@ -0,0 +1,529 @@
|
||||
// Version 1.5
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Permissions;
|
||||
using System.Threading;
|
||||
|
||||
namespace SevenZipExtractor
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct PropArray
|
||||
{
|
||||
uint length;
|
||||
IntPtr pointerValues;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
internal struct PropVariant
|
||||
{
|
||||
[DllImport("ole32.dll")]
|
||||
private static extern int PropVariantClear(ref PropVariant pvar);
|
||||
|
||||
[FieldOffset(0)] public ushort vt;
|
||||
[FieldOffset(8)] public IntPtr pointerValue;
|
||||
[FieldOffset(8)] public byte byteValue;
|
||||
[FieldOffset(8)] public long longValue;
|
||||
[FieldOffset(8)] public System.Runtime.InteropServices.ComTypes.FILETIME filetime;
|
||||
[FieldOffset(8)] public PropArray propArray;
|
||||
|
||||
public VarEnum VarType
|
||||
{
|
||||
get
|
||||
{
|
||||
return (VarEnum) this.vt;
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
switch (this.VarType)
|
||||
{
|
||||
case VarEnum.VT_EMPTY:
|
||||
break;
|
||||
|
||||
case VarEnum.VT_NULL:
|
||||
case VarEnum.VT_I2:
|
||||
case VarEnum.VT_I4:
|
||||
case VarEnum.VT_R4:
|
||||
case VarEnum.VT_R8:
|
||||
case VarEnum.VT_CY:
|
||||
case VarEnum.VT_DATE:
|
||||
case VarEnum.VT_ERROR:
|
||||
case VarEnum.VT_BOOL:
|
||||
//case VarEnum.VT_DECIMAL:
|
||||
case VarEnum.VT_I1:
|
||||
case VarEnum.VT_UI1:
|
||||
case VarEnum.VT_UI2:
|
||||
case VarEnum.VT_UI4:
|
||||
case VarEnum.VT_I8:
|
||||
case VarEnum.VT_UI8:
|
||||
case VarEnum.VT_INT:
|
||||
case VarEnum.VT_UINT:
|
||||
case VarEnum.VT_HRESULT:
|
||||
case VarEnum.VT_FILETIME:
|
||||
this.vt = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
PropVariantClear(ref this);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public object GetObject()
|
||||
{
|
||||
switch (this.VarType)
|
||||
{
|
||||
case VarEnum.VT_EMPTY:
|
||||
return null;
|
||||
|
||||
case VarEnum.VT_FILETIME:
|
||||
return DateTime.FromFileTime(this.longValue);
|
||||
|
||||
default:
|
||||
GCHandle PropHandle = GCHandle.Alloc(this, GCHandleType.Pinned);
|
||||
|
||||
try
|
||||
{
|
||||
return Marshal.GetObjectForNativeVariant(PropHandle.AddrOfPinnedObject());
|
||||
}
|
||||
finally
|
||||
{
|
||||
PropHandle.Free();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[ComImport]
|
||||
[Guid("23170F69-40C1-278A-0000-000000050000")]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
internal interface IProgress
|
||||
{
|
||||
void SetTotal(ulong total);
|
||||
void SetCompleted([In] ref ulong completeValue);
|
||||
}
|
||||
|
||||
[ComImport]
|
||||
[Guid("23170F69-40C1-278A-0000-000600100000")]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
internal interface IArchiveOpenCallback
|
||||
{
|
||||
// ref ulong replaced with IntPtr because handlers ofter pass null value
|
||||
// read actual value with Marshal.ReadInt64
|
||||
void SetTotal(
|
||||
IntPtr files, // [In] ref ulong files, can use 'ulong* files' but it is unsafe
|
||||
IntPtr bytes); // [In] ref ulong bytes
|
||||
|
||||
void SetCompleted(
|
||||
IntPtr files, // [In] ref ulong files
|
||||
IntPtr bytes); // [In] ref ulong bytes
|
||||
}
|
||||
|
||||
[ComImport]
|
||||
[Guid("23170F69-40C1-278A-0000-000500100000")]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
internal interface ICryptoGetTextPassword
|
||||
{
|
||||
[PreserveSig]
|
||||
int CryptoGetTextPassword(
|
||||
[MarshalAs(UnmanagedType.BStr)] out string password);
|
||||
|
||||
//[return : MarshalAs(UnmanagedType.BStr)]
|
||||
//string CryptoGetTextPassword();
|
||||
}
|
||||
|
||||
internal enum AskMode : int
|
||||
{
|
||||
kExtract = 0,
|
||||
kTest,
|
||||
kSkip
|
||||
}
|
||||
|
||||
internal enum OperationResult : int
|
||||
{
|
||||
kOK = 0,
|
||||
kUnSupportedMethod,
|
||||
kDataError,
|
||||
kCRCError
|
||||
}
|
||||
|
||||
[ComImport]
|
||||
[Guid("23170F69-40C1-278A-0000-000600300000")]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
internal interface IArchiveOpenVolumeCallback
|
||||
{
|
||||
void GetProperty(
|
||||
ItemPropId propID, // PROPID
|
||||
IntPtr value); // PROPVARIANT
|
||||
|
||||
[PreserveSig]
|
||||
int GetStream(
|
||||
[MarshalAs(UnmanagedType.LPWStr)] string name,
|
||||
[MarshalAs(UnmanagedType.Interface)] out IInStream inStream);
|
||||
}
|
||||
|
||||
[ComImport]
|
||||
[Guid("23170F69-40C1-278A-0000-000600400000")]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
internal interface IInArchiveGetStream
|
||||
{
|
||||
[return: MarshalAs(UnmanagedType.Interface)]
|
||||
ISequentialInStream GetStream(uint index);
|
||||
}
|
||||
|
||||
[ComImport]
|
||||
[Guid("23170F69-40C1-278A-0000-000300010000")]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
internal interface ISequentialInStream
|
||||
{
|
||||
//[PreserveSig]
|
||||
//int Read(
|
||||
// [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] data,
|
||||
// uint size,
|
||||
// IntPtr processedSize); // ref uint processedSize
|
||||
|
||||
uint Read(
|
||||
[Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] data,
|
||||
uint size);
|
||||
|
||||
/*
|
||||
Out: if size != 0, return_value = S_OK and (*processedSize == 0),
|
||||
then there are no more bytes in stream.
|
||||
if (size > 0) && there are bytes in stream,
|
||||
this function must read at least 1 byte.
|
||||
This function is allowed to read less than number of remaining bytes in stream.
|
||||
You must call Read function in loop, if you need exact amount of data
|
||||
*/
|
||||
}
|
||||
|
||||
[ComImport]
|
||||
[Guid("23170F69-40C1-278A-0000-000300020000")]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
internal interface ISequentialOutStream
|
||||
{
|
||||
[PreserveSig]
|
||||
int Write(
|
||||
[In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] data,
|
||||
uint size,
|
||||
IntPtr processedSize); // ref uint processedSize
|
||||
/*
|
||||
if (size > 0) this function must write at least 1 byte.
|
||||
This function is allowed to write less than "size".
|
||||
You must call Write function in loop, if you need to write exact amount of data
|
||||
*/
|
||||
}
|
||||
|
||||
[ComImport]
|
||||
[Guid("23170F69-40C1-278A-0000-000300030000")]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
internal interface IInStream //: ISequentialInStream
|
||||
{
|
||||
//[PreserveSig]
|
||||
//int Read(
|
||||
// [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] data,
|
||||
// uint size,
|
||||
// IntPtr processedSize); // ref uint processedSize
|
||||
|
||||
uint Read(
|
||||
[Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] data,
|
||||
uint size);
|
||||
|
||||
//[PreserveSig]
|
||||
void Seek(
|
||||
long offset,
|
||||
uint seekOrigin,
|
||||
IntPtr newPosition); // ref long newPosition
|
||||
}
|
||||
|
||||
[ComImport]
|
||||
[Guid("23170F69-40C1-278A-0000-000300040000")]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
internal interface IOutStream //: ISequentialOutStream
|
||||
{
|
||||
[PreserveSig]
|
||||
int Write(
|
||||
[In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] data,
|
||||
uint size,
|
||||
IntPtr processedSize); // ref uint processedSize
|
||||
|
||||
//[PreserveSig]
|
||||
void Seek(
|
||||
long offset,
|
||||
uint seekOrigin,
|
||||
IntPtr newPosition); // ref long newPosition
|
||||
|
||||
[PreserveSig]
|
||||
int SetSize(long newSize);
|
||||
}
|
||||
|
||||
internal enum ItemPropId : uint
|
||||
{
|
||||
kpidNoProperty = 0,
|
||||
|
||||
kpidHandlerItemIndex = 2,
|
||||
kpidPath,
|
||||
kpidName,
|
||||
kpidExtension,
|
||||
kpidIsFolder,
|
||||
kpidSize,
|
||||
kpidPackedSize,
|
||||
kpidAttributes,
|
||||
kpidCreationTime,
|
||||
kpidLastAccessTime,
|
||||
kpidLastWriteTime,
|
||||
kpidSolid,
|
||||
kpidCommented,
|
||||
kpidEncrypted,
|
||||
kpidSplitBefore,
|
||||
kpidSplitAfter,
|
||||
kpidDictionarySize,
|
||||
kpidCRC,
|
||||
kpidType,
|
||||
kpidIsAnti,
|
||||
kpidMethod,
|
||||
kpidHostOS,
|
||||
kpidFileSystem,
|
||||
kpidUser,
|
||||
kpidGroup,
|
||||
kpidBlock,
|
||||
kpidComment,
|
||||
kpidPosition,
|
||||
kpidPrefix,
|
||||
|
||||
kpidTotalSize = 0x1100,
|
||||
kpidFreeSpace,
|
||||
kpidClusterSize,
|
||||
kpidVolumeName,
|
||||
|
||||
kpidLocalName = 0x1200,
|
||||
kpidProvider,
|
||||
|
||||
kpidUserDefined = 0x10000
|
||||
}
|
||||
|
||||
|
||||
[ComImport]
|
||||
[Guid("23170F69-40C1-278A-0000-000600600000")]
|
||||
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
||||
//[AutomationProxy(true)]
|
||||
internal interface IInArchive
|
||||
{
|
||||
[PreserveSig]
|
||||
int Open(
|
||||
IInStream stream,
|
||||
/*[MarshalAs(UnmanagedType.U8)]*/ [In] ref ulong maxCheckStartPosition,
|
||||
[MarshalAs(UnmanagedType.Interface)] IArchiveOpenCallback openArchiveCallback);
|
||||
|
||||
void Close();
|
||||
//void GetNumberOfItems([In] ref uint numItem);
|
||||
uint GetNumberOfItems();
|
||||
|
||||
void GetProperty(
|
||||
uint index,
|
||||
ItemPropId propID, // PROPID
|
||||
ref PropVariant value); // PROPVARIANT
|
||||
|
||||
[PreserveSig]
|
||||
int Extract(
|
||||
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] uint[] indices, //[In] ref uint indices,
|
||||
uint numItems,
|
||||
int testMode,
|
||||
[MarshalAs(UnmanagedType.Interface)] IArchiveExtractCallback extractCallback);
|
||||
|
||||
// indices must be sorted
|
||||
// numItems = 0xFFFFFFFF means all files
|
||||
// testMode != 0 means "test files operation"
|
||||
|
||||
void GetArchiveProperty(
|
||||
uint propID, // PROPID
|
||||
ref PropVariant value); // PROPVARIANT
|
||||
|
||||
//void GetNumberOfProperties([In] ref uint numProperties);
|
||||
uint GetNumberOfProperties();
|
||||
|
||||
void GetPropertyInfo(
|
||||
uint index,
|
||||
[MarshalAs(UnmanagedType.BStr)] out string name,
|
||||
out ItemPropId propID, // PROPID
|
||||
out ushort varType); //VARTYPE
|
||||
|
||||
//void GetNumberOfArchiveProperties([In] ref uint numProperties);
|
||||
uint GetNumberOfArchiveProperties();
|
||||
|
||||
void GetArchivePropertyInfo(
|
||||
uint index,
|
||||
[MarshalAs(UnmanagedType.BStr)] string name,
|
||||
ref uint propID, // PROPID
|
||||
ref ushort varType); //VARTYPE
|
||||
}
|
||||
|
||||
internal enum ArchivePropId : uint
|
||||
{
|
||||
kName = 0,
|
||||
kClassID,
|
||||
kExtension,
|
||||
kAddExtension,
|
||||
kUpdate,
|
||||
kKeepName,
|
||||
kStartSignature,
|
||||
kFinishSignature,
|
||||
kAssociate
|
||||
}
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
|
||||
internal delegate int CreateObjectDelegate(
|
||||
[In] ref Guid classID,
|
||||
[In] ref Guid interfaceID,
|
||||
//out IntPtr outObject);
|
||||
[MarshalAs(UnmanagedType.Interface)] out object outObject);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
|
||||
internal delegate int GetHandlerPropertyDelegate(
|
||||
ArchivePropId propID,
|
||||
ref PropVariant value); // PROPVARIANT
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
|
||||
internal delegate int GetNumberOfFormatsDelegate(out uint numFormats);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
|
||||
internal delegate int GetHandlerProperty2Delegate(
|
||||
uint formatIndex,
|
||||
ArchivePropId propID,
|
||||
ref PropVariant value); // PROPVARIANT
|
||||
|
||||
internal class StreamWrapper : IDisposable
|
||||
{
|
||||
protected Stream BaseStream;
|
||||
|
||||
protected StreamWrapper(Stream baseStream)
|
||||
{
|
||||
this.BaseStream = baseStream;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
this.BaseStream.Close();
|
||||
}
|
||||
|
||||
public virtual void Seek(long offset, uint seekOrigin, IntPtr newPosition)
|
||||
{
|
||||
long Position = (uint) this.BaseStream.Seek(offset, (SeekOrigin) seekOrigin);
|
||||
if (newPosition != IntPtr.Zero)
|
||||
{
|
||||
Marshal.WriteInt64(newPosition, Position);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class InStreamWrapper : StreamWrapper, ISequentialInStream, IInStream
|
||||
{
|
||||
public InStreamWrapper(Stream baseStream) : base(baseStream)
|
||||
{
|
||||
}
|
||||
|
||||
public uint Read(byte[] data, uint size)
|
||||
{
|
||||
return (uint) this.BaseStream.Read(data, 0, (int) size);
|
||||
}
|
||||
}
|
||||
|
||||
// Can close base stream after period of inactivity and reopen it when needed.
|
||||
// Useful for long opened archives (prevent locking archive file on disk).
|
||||
internal class InStreamTimedWrapper : StreamWrapper, ISequentialInStream, IInStream
|
||||
{
|
||||
private string BaseStreamFileName;
|
||||
private long BaseStreamLastPosition;
|
||||
private Timer CloseTimer;
|
||||
|
||||
private const int KeepAliveInterval = 10 * 1000; // 10 sec
|
||||
|
||||
public InStreamTimedWrapper(Stream baseStream)
|
||||
: base(baseStream)
|
||||
{
|
||||
if ((this.BaseStream is FileStream) && !this.BaseStream.CanWrite && this.BaseStream.CanSeek)
|
||||
{
|
||||
this.BaseStreamFileName = ((FileStream) this.BaseStream).Name;
|
||||
this.CloseTimer = new Timer(new TimerCallback(this.CloseStream), null, KeepAliveInterval, Timeout.Infinite);
|
||||
}
|
||||
}
|
||||
|
||||
private void CloseStream(object state)
|
||||
{
|
||||
if (this.CloseTimer != null)
|
||||
{
|
||||
this.CloseTimer.Dispose();
|
||||
this.CloseTimer = null;
|
||||
}
|
||||
|
||||
if (this.BaseStream != null)
|
||||
{
|
||||
if (this.BaseStream.CanSeek)
|
||||
{
|
||||
this.BaseStreamLastPosition = this.BaseStream.Position;
|
||||
}
|
||||
this.BaseStream.Close();
|
||||
this.BaseStream = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected void ReopenStream()
|
||||
{
|
||||
if (this.BaseStream == null)
|
||||
{
|
||||
if (this.BaseStreamFileName != null)
|
||||
{
|
||||
this.BaseStream = new FileStream(this.BaseStreamFileName, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
this.BaseStream.Position = this.BaseStreamLastPosition;
|
||||
this.CloseTimer = new Timer(new TimerCallback(this.CloseStream), null, KeepAliveInterval, Timeout.Infinite);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ObjectDisposedException("StreamWrapper");
|
||||
}
|
||||
}
|
||||
else if (this.CloseTimer != null)
|
||||
{
|
||||
this.CloseTimer.Change(KeepAliveInterval, Timeout.Infinite);
|
||||
}
|
||||
}
|
||||
|
||||
public uint Read(byte[] data, uint size)
|
||||
{
|
||||
this.ReopenStream();
|
||||
return (uint) this.BaseStream.Read(data, 0, (int) size);
|
||||
}
|
||||
|
||||
public override void Seek(long offset, uint seekOrigin, IntPtr newPosition)
|
||||
{
|
||||
this.ReopenStream();
|
||||
base.Seek(offset, seekOrigin, newPosition);
|
||||
}
|
||||
}
|
||||
|
||||
internal class OutStreamWrapper : StreamWrapper, ISequentialOutStream, IOutStream
|
||||
{
|
||||
public OutStreamWrapper(Stream baseStream) : base(baseStream)
|
||||
{
|
||||
}
|
||||
|
||||
public int SetSize(long newSize)
|
||||
{
|
||||
this.BaseStream.SetLength(newSize);
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int Write(byte[] data, uint size, IntPtr processedSize)
|
||||
{
|
||||
this.BaseStream.Write(data, 0, (int) size);
|
||||
if (processedSize != IntPtr.Zero)
|
||||
{
|
||||
Marshal.WriteInt32(processedSize, (int) size);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
13
Wabbajack.Common/Consts.cs
Normal file
13
Wabbajack.Common/Consts.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Wabbajack.Common
|
||||
{
|
||||
public static class Consts
|
||||
{
|
||||
public static string GameFolderFilesDir = "Game Folder Files";
|
||||
}
|
||||
}
|
191
Wabbajack.Common/Data.cs
Normal file
191
Wabbajack.Common/Data.cs
Normal file
@ -0,0 +1,191 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Wabbajack.Common
|
||||
{
|
||||
public class RawSourceFile
|
||||
{
|
||||
public string AbsolutePath;
|
||||
public string Path;
|
||||
|
||||
private string _hash;
|
||||
public string Hash
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_hash != null) return _hash;
|
||||
_hash = AbsolutePath.FileSHA256();
|
||||
return _hash;
|
||||
}
|
||||
}
|
||||
|
||||
public T EvolveTo<T>() where T : Directive, new()
|
||||
{
|
||||
var v = new T();
|
||||
v.To = Path;
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
public class ModList
|
||||
{
|
||||
/// <summary>
|
||||
/// Name of the ModList
|
||||
/// </summary>
|
||||
public string Name;
|
||||
/// <summary>
|
||||
/// Author of the Mod List
|
||||
/// </summary>
|
||||
public string Author;
|
||||
/// <summary>
|
||||
/// Version of this Mod List
|
||||
/// </summary>
|
||||
public string Version;
|
||||
|
||||
/// <summary>
|
||||
/// Install directives
|
||||
/// </summary>
|
||||
public List<Directive> Directives;
|
||||
|
||||
/// <summary>
|
||||
/// Archives required by this modlist
|
||||
/// </summary>
|
||||
public List<Archive> Archives;
|
||||
}
|
||||
|
||||
public class Directive
|
||||
{
|
||||
/// <summary>
|
||||
/// location the file will be copied to, relative to the install path.
|
||||
/// </summary>
|
||||
public string To;
|
||||
}
|
||||
|
||||
public class IgnoredDirectly : Directive
|
||||
{
|
||||
public string Reason;
|
||||
}
|
||||
|
||||
public class NoMatch : IgnoredDirectly
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public class InlineFile : Directive
|
||||
{
|
||||
/// <summary>
|
||||
/// Data that will be written as-is to the destination location;
|
||||
/// </summary>
|
||||
public string SourceData;
|
||||
}
|
||||
|
||||
public class FromArchive : Directive
|
||||
{
|
||||
/// <summary>
|
||||
/// MurMur3 hash of the archive this file comes from
|
||||
/// </summary>
|
||||
public string ArchiveHash;
|
||||
/// <summary>
|
||||
/// The relative path of the file in the archive
|
||||
/// </summary>
|
||||
public string From;
|
||||
}
|
||||
|
||||
public class PatchedArchive : FromArchive
|
||||
{
|
||||
/// <summary>
|
||||
/// The file to apply to the source file to patch it
|
||||
/// </summary>
|
||||
public string Patch;
|
||||
}
|
||||
|
||||
public class Archive
|
||||
{
|
||||
/// <summary>
|
||||
/// MurMur3 Hash of the archive
|
||||
/// </summary>
|
||||
public string Hash;
|
||||
/// <summary>
|
||||
/// Human friendly name of this archive
|
||||
/// </summary>
|
||||
public string Name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// URL that can be downloaded directly without any additional options
|
||||
/// </summary>
|
||||
public class DirectURLArchive : Archive
|
||||
{
|
||||
public string URL;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An archive that requires additional HTTP headers.
|
||||
/// </summary>
|
||||
public class DirectURLArchiveEx : DirectURLArchive
|
||||
{
|
||||
public Dictionary<string, string> Headers;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Archive that comes from MEGA
|
||||
/// </summary>
|
||||
public class MEGAArchive : DirectURLArchive
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Archive that comes from MODDB
|
||||
/// </summary>
|
||||
public class MODDBArchive : DirectURLArchive
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The indexed contents of an archive
|
||||
/// </summary>
|
||||
public class IndexedArchiveCache
|
||||
{
|
||||
public string Hash;
|
||||
public List<IndexedEntry> Entries;
|
||||
}
|
||||
|
||||
public class IndexedArchive : IndexedArchiveCache
|
||||
{
|
||||
public dynamic IniData;
|
||||
public string Name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A archive entry
|
||||
/// </summary>
|
||||
public class IndexedEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// Path in the archive to this file
|
||||
/// </summary>
|
||||
public string Path;
|
||||
/// <summary>
|
||||
/// MurMur3 hash of this file
|
||||
/// </summary>
|
||||
public string Hash;
|
||||
/// <summary>
|
||||
/// Size of the file (uncompressed)
|
||||
/// </summary>
|
||||
public long Size;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Data found inside a BSA file in an archive
|
||||
/// </summary>
|
||||
public class BSAIndexedEntry : IndexedEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// MurMur3 hash of the BSA this file comes from
|
||||
/// </summary>
|
||||
public string BSAHash;
|
||||
}
|
||||
}
|
53
Wabbajack.Common/DynamicIniData.cs
Normal file
53
Wabbajack.Common/DynamicIniData.cs
Normal file
@ -0,0 +1,53 @@
|
||||
using IniParser;
|
||||
using IniParser.Model;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Dynamic;
|
||||
using System.Text;
|
||||
|
||||
namespace Wabbajack.Common
|
||||
{
|
||||
public class DynamicIniData : DynamicObject
|
||||
{
|
||||
private IniData value;
|
||||
|
||||
public DynamicIniData(IniData value) //
|
||||
{
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public static dynamic FromIni(IniData data)
|
||||
{
|
||||
return new DynamicIniData(data);
|
||||
}
|
||||
|
||||
public static dynamic FromFile(string filename)
|
||||
{
|
||||
var fi = new FileIniDataParser();
|
||||
return new DynamicIniData(fi.ReadFile(filename));
|
||||
}
|
||||
|
||||
public override bool TryGetMember(GetMemberBinder binder, out object result)
|
||||
{
|
||||
result = new SectionData(value[binder.Name]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class SectionData : DynamicObject
|
||||
{
|
||||
private KeyDataCollection _coll;
|
||||
|
||||
public SectionData(KeyDataCollection coll)
|
||||
{
|
||||
this._coll = coll;
|
||||
}
|
||||
|
||||
public override bool TryGetMember(GetMemberBinder binder, out object result)
|
||||
{
|
||||
result = _coll[binder.Name];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
36
Wabbajack.Common/Properties/AssemblyInfo.cs
Normal file
36
Wabbajack.Common/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("Wabbajack.Common")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Wabbajack.Common")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2019")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("b3f3fb6e-b9eb-4f49-9875-d78578bc7ae5")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
88
Wabbajack.Common/Utils.cs
Normal file
88
Wabbajack.Common/Utils.cs
Normal file
@ -0,0 +1,88 @@
|
||||
using IniParser;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Wabbajack.Common
|
||||
{
|
||||
public static class Utils
|
||||
{
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// MurMur3 hashes the file pointed to by this string
|
||||
/// </summary>
|
||||
/// <param name="file"></param>
|
||||
/// <returns></returns>
|
||||
public static string FileSHA256(this string file)
|
||||
{
|
||||
var sha = new SHA256Managed();
|
||||
using (var o = new CryptoStream(Stream.Null, sha, CryptoStreamMode.Write))
|
||||
{
|
||||
using (var i = File.OpenRead(file))
|
||||
i.CopyTo(o);
|
||||
}
|
||||
return sha.Hash.ToBase64();
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a Base64 encoding of these bytes
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <returns></returns>
|
||||
public static string ToBase64(this byte[] data)
|
||||
{
|
||||
return Convert.ToBase64String(data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes the action for every item in coll
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="coll"></param>
|
||||
/// <param name="f"></param>
|
||||
public static void Do<T>(this IEnumerable<T> coll, Action<T> f)
|
||||
{
|
||||
foreach (var i in coll) f(i);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads INI data from the given filename and returns a dynamic type that
|
||||
/// can use . operators to navigate the INI.
|
||||
/// </summary>
|
||||
/// <param name="file"></param>
|
||||
/// <returns></returns>
|
||||
public static dynamic LoadIniFile(this string file)
|
||||
{
|
||||
return new DynamicIniData(new FileIniDataParser().ReadFile(file));
|
||||
}
|
||||
|
||||
public static void ToJSON<T>(this T obj, string filename)
|
||||
{
|
||||
File.WriteAllText(filename, JsonConvert.SerializeObject(obj, Formatting.Indented, new JsonSerializerSettings() {TypeNameHandling = TypeNameHandling.Auto}));
|
||||
}
|
||||
|
||||
public static T FromJSON<T>(this string filename)
|
||||
{
|
||||
return JsonConvert.DeserializeObject<T>(File.ReadAllText(filename));
|
||||
}
|
||||
|
||||
public static bool FileExists(this string filename)
|
||||
{
|
||||
return File.Exists(filename);
|
||||
}
|
||||
|
||||
public static string RelativeTo(this string file, string folder)
|
||||
{
|
||||
return file.Substring(folder.Length + 1);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
71
Wabbajack.Common/Wabbajack.Common.csproj
Normal file
71
Wabbajack.Common/Wabbajack.Common.csproj
Normal file
@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{B3F3FB6E-B9EB-4F49-9875-D78578BC7AE5}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Wabbajack.Common</RootNamespace>
|
||||
<AssemblyName>Wabbajack.Common</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="INIFileParser, Version=2.5.2.0, Culture=neutral, PublicKeyToken=79af7b307b65cf3c, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\ini-parser.2.5.2\lib\net20\INIFileParser.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Numerics" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Consts.cs" />
|
||||
<Compile Include="Data.cs" />
|
||||
<Compile Include="DynamicIniData.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Utils.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\BSA.Tools\BSA.Tools.csproj">
|
||||
<Project>{b6389807-ea59-4633-b42b-a85f52fec135}</Project>
|
||||
<Name>BSA.Tools</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\SevenZipExtractor\SevenZipExtractor.csproj">
|
||||
<Project>{8aa97f58-5044-4bba-b8d9-a74b6947a660}</Project>
|
||||
<Name>SevenZipExtractor</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
10
Wabbajack.Common/packages.config
Normal file
10
Wabbajack.Common/packages.config
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="ini-parser" version="2.5.2" targetFramework="net472" />
|
||||
<package id="murmurhash" version="1.0.3" targetFramework="net472" />
|
||||
<package id="Newtonsoft.Json" version="12.0.2" targetFramework="net472" />
|
||||
<package id="System.Data.HashFunction.Core" version="2.0.0" targetFramework="net472" />
|
||||
<package id="System.Data.HashFunction.Interfaces" version="2.0.0" targetFramework="net472" />
|
||||
<package id="System.Data.HashFunction.MurmurHash" version="2.0.0" targetFramework="net472" />
|
||||
<package id="System.Runtime.Numerics" version="4.3.0" targetFramework="net472" />
|
||||
</packages>
|
43
Wabbajack.sln
Normal file
43
Wabbajack.sln
Normal file
@ -0,0 +1,43 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.29102.190
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wabbajack", "Wabbajack\Wabbajack.csproj", "{1649CAB3-6F8E-4F2E-844C-931BD4B61233}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wabbajack.Common", "Wabbajack.Common\Wabbajack.Common.csproj", "{B3F3FB6E-B9EB-4F49-9875-D78578BC7AE5}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BSA.Tools", "BSA.Tools\BSA.Tools.csproj", "{B6389807-EA59-4633-B42B-A85F52FEC135}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SevenZipExtractor", "SevenZipExtractor\SevenZipExtractor.csproj", "{8AA97F58-5044-4BBA-B8D9-A74B6947A660}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{1649CAB3-6F8E-4F2E-844C-931BD4B61233}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1649CAB3-6F8E-4F2E-844C-931BD4B61233}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1649CAB3-6F8E-4F2E-844C-931BD4B61233}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1649CAB3-6F8E-4F2E-844C-931BD4B61233}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B3F3FB6E-B9EB-4F49-9875-D78578BC7AE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B3F3FB6E-B9EB-4F49-9875-D78578BC7AE5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B3F3FB6E-B9EB-4F49-9875-D78578BC7AE5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B3F3FB6E-B9EB-4F49-9875-D78578BC7AE5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B6389807-EA59-4633-B42B-A85F52FEC135}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B6389807-EA59-4633-B42B-A85F52FEC135}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B6389807-EA59-4633-B42B-A85F52FEC135}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B6389807-EA59-4633-B42B-A85F52FEC135}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8AA97F58-5044-4BBA-B8D9-A74B6947A660}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8AA97F58-5044-4BBA-B8D9-A74B6947A660}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8AA97F58-5044-4BBA-B8D9-A74B6947A660}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8AA97F58-5044-4BBA-B8D9-A74B6947A660}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {5CF408D5-8BF2-40C2-907C-694DBACFF01B}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
6
Wabbajack/App.config
Normal file
6
Wabbajack/App.config
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
|
||||
</startup>
|
||||
</configuration>
|
248
Wabbajack/Compiler.cs
Normal file
248
Wabbajack/Compiler.cs
Normal file
@ -0,0 +1,248 @@
|
||||
using Murmur;
|
||||
using SevenZipExtractor;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using Wabbajack.Common;
|
||||
|
||||
namespace Wabbajack
|
||||
{
|
||||
public class Compiler
|
||||
{
|
||||
public static HashSet<string> SupportedArchives = new HashSet<string>() { ".zip", ".rar", ".7z", ".7zip" };
|
||||
|
||||
|
||||
public string MO2Folder;
|
||||
|
||||
public dynamic MO2Ini { get; }
|
||||
public string GamePath { get; }
|
||||
|
||||
public string MO2DownloadsFolder {
|
||||
get
|
||||
{
|
||||
return Path.Combine(MO2Folder, "downloads");
|
||||
}
|
||||
}
|
||||
|
||||
public Action<string> Log_Fn { get; }
|
||||
public Action<string, long, long> Progress_Function { get; }
|
||||
|
||||
public List<IndexedArchive> IndexedArchives;
|
||||
|
||||
public void Info(string msg, params object[] args)
|
||||
{
|
||||
if (args.Length > 0)
|
||||
msg = String.Format(msg, args);
|
||||
Log_Fn(msg);
|
||||
}
|
||||
|
||||
public Compiler(string mo2_folder, Action<string> log_fn, Action<string, long, long> progress_function)
|
||||
{
|
||||
MO2Folder = mo2_folder;
|
||||
Log_Fn = log_fn;
|
||||
Progress_Function = progress_function;
|
||||
MO2Ini = Path.Combine(MO2Folder, "ModOrganizer.ini").LoadIniFile();
|
||||
GamePath = ((string)MO2Ini.General.gamePath).Replace("\\\\", "\\");
|
||||
}
|
||||
|
||||
public void LoadArchives()
|
||||
{
|
||||
IndexedArchives = Directory.EnumerateFiles(MO2DownloadsFolder)
|
||||
.Where(file => SupportedArchives.Contains(Path.GetExtension(file)))
|
||||
.AsParallel()
|
||||
.Select(file => LoadArchive(file))
|
||||
.ToList();
|
||||
}
|
||||
|
||||
private IndexedArchive LoadArchive(string file)
|
||||
{
|
||||
string metaname = file + ".archive_contents";
|
||||
|
||||
if (metaname.FileExists() && new FileInfo(metaname).LastWriteTime >= new FileInfo(file).LastWriteTime)
|
||||
{
|
||||
var info = metaname.FromJSON<IndexedArchive>();
|
||||
info.Name = Path.GetFileName(file);
|
||||
|
||||
var ini_name = file + ".meta";
|
||||
if (ini_name.FileExists())
|
||||
info.IniData = ini_name.LoadIniFile();
|
||||
return info;
|
||||
}
|
||||
|
||||
using (var ar = new ArchiveFile(file))
|
||||
{
|
||||
var streams = new Dictionary<string, (SHA256Managed, long)>();
|
||||
ar.Extract(entry => {
|
||||
if (entry.IsFolder) return null;
|
||||
|
||||
var sha = new SHA256Managed();
|
||||
var os = new CryptoStream(Stream.Null, sha, CryptoStreamMode.Write);
|
||||
streams.Add(entry.FileName, (sha, (long)entry.Size));
|
||||
return os;
|
||||
});
|
||||
|
||||
var indexed = new IndexedArchiveCache();
|
||||
indexed.Hash = file.FileSHA256();
|
||||
indexed.Entries = streams.Select(entry =>
|
||||
{
|
||||
return new IndexedEntry()
|
||||
{
|
||||
Hash = entry.Value.Item1.Hash.ToBase64(),
|
||||
Size = (long)entry.Value.Item2,
|
||||
Path = entry.Key
|
||||
};
|
||||
}).ToList();
|
||||
|
||||
streams.Do(e => e.Value.Item1.Dispose());
|
||||
|
||||
indexed.ToJSON(metaname);
|
||||
return LoadArchive(file);
|
||||
}
|
||||
}
|
||||
|
||||
public void Compile()
|
||||
{
|
||||
var mo2_files = Directory.EnumerateFiles(MO2Folder, "*", SearchOption.AllDirectories)
|
||||
.Where(p => p.FileExists())
|
||||
.Select(p => new RawSourceFile() { Path = p.RelativeTo(MO2Folder), AbsolutePath = p });
|
||||
|
||||
var game_files = Directory.EnumerateFiles(GamePath, "*", SearchOption.AllDirectories)
|
||||
.Where(p => p.FileExists())
|
||||
.Select(p => new RawSourceFile() { Path = Path.Combine(Consts.GameFolderFilesDir, p.RelativeTo(GamePath)), AbsolutePath = p });
|
||||
|
||||
var all_files = mo2_files.Concat(game_files).ToList();
|
||||
|
||||
Info("Found {0} files to build into mod list", all_files.Count);
|
||||
|
||||
var stack = MakeStack();
|
||||
|
||||
var results = all_files.AsParallel().Select(f => RunStack(stack, f)).ToList();
|
||||
|
||||
var nomatch = results.OfType<NoMatch>();
|
||||
Info("No match for {0} files", nomatch.Count());
|
||||
foreach (var file in nomatch)
|
||||
Info(" {0}", file.To);
|
||||
|
||||
results.ToJSON("out.json");
|
||||
|
||||
}
|
||||
|
||||
private Directive RunStack(IEnumerable<Func<RawSourceFile, Directive>> stack, RawSourceFile source)
|
||||
{
|
||||
return (from f in stack
|
||||
let result = f(source)
|
||||
where result != null
|
||||
select result).First();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates a execution stack. The stack should be passed into Run stack. Each function
|
||||
/// in this stack will be run in-order and the first to return a non-null result will have its
|
||||
/// result included into the pack
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private IEnumerable<Func<RawSourceFile, Directive>> MakeStack()
|
||||
{
|
||||
Info("Generating compilation stack");
|
||||
return new List<Func<RawSourceFile, Directive>>()
|
||||
{
|
||||
IgnoreStartsWith("logs\\"),
|
||||
IgnoreStartsWith("downloads\\"),
|
||||
IgnoreStartsWith("webcache\\"),
|
||||
IgnoreEndsWith(".pyc"),
|
||||
// Ignore the ModOrganizer.ini file it contains info created by MO2 on startup
|
||||
IgnoreStartsWith("ModOrganizer.ini"),
|
||||
IgnoreRegex(Consts.GameFolderFilesDir + "\\\\.*\\.bsa"),
|
||||
DirectMatch(),
|
||||
DropAll()
|
||||
};
|
||||
}
|
||||
|
||||
private Func<RawSourceFile, Directive> IgnoreEndsWith(string v)
|
||||
{
|
||||
var reason = String.Format("Ignored because path ends with {0}", v);
|
||||
return source =>
|
||||
{
|
||||
if (source.Path.EndsWith(v))
|
||||
{
|
||||
var result = source.EvolveTo<IgnoredDirectly>();
|
||||
result.Reason = reason;
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
}
|
||||
|
||||
private Func<RawSourceFile, Directive> IgnoreRegex(string p)
|
||||
{
|
||||
var reason = String.Format("Ignored because path matches regex {0}", p);
|
||||
var regex = new Regex(p);
|
||||
return source =>
|
||||
{
|
||||
if (regex.IsMatch(source.Path))
|
||||
{
|
||||
var result = source.EvolveTo<IgnoredDirectly>();
|
||||
result.Reason = reason;
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
}
|
||||
|
||||
private Func<RawSourceFile, Directive> DropAll()
|
||||
{
|
||||
return source => {
|
||||
var result = source.EvolveTo<NoMatch>();
|
||||
result.Reason = "No Match in Stack";
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
private Func<RawSourceFile, Directive> DirectMatch()
|
||||
{
|
||||
var indexed = (from archive in IndexedArchives
|
||||
from entry in archive.Entries
|
||||
select new { archive = archive, entry = entry })
|
||||
.GroupBy(e => e.entry.Hash)
|
||||
.ToDictionary(e => e.Key);
|
||||
|
||||
return source =>
|
||||
{
|
||||
Info("Hashing {0}", source.Path);
|
||||
if (indexed.TryGetValue(source.Hash, out var found))
|
||||
{
|
||||
var result = source.EvolveTo<FromArchive>();
|
||||
var match = found.FirstOrDefault(f => Path.GetFileName(f.entry.Path) == Path.GetFileName(source.Path));
|
||||
if (match == null)
|
||||
match = found.First();
|
||||
|
||||
result.ArchiveHash = match.archive.Hash;
|
||||
result.From = match.entry.Path;
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
}
|
||||
|
||||
private Func<RawSourceFile, Directive> IgnoreStartsWith(string v)
|
||||
{
|
||||
var reason = String.Format("Ignored because path starts with {0}", v);
|
||||
return source =>
|
||||
{
|
||||
if (source.Path.StartsWith(v))
|
||||
{
|
||||
var result = source.EvolveTo<IgnoredDirectly>();
|
||||
result.Reason = reason;
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
20
Wabbajack/Program.cs
Normal file
20
Wabbajack/Program.cs
Normal file
@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Wabbajack.Common;
|
||||
|
||||
namespace Wabbajack
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
var compiler = new Compiler("c:\\Mod Organizer 2", msg => Console.WriteLine(msg), (msg, id, prog) => Console.WriteLine(msg));
|
||||
compiler.LoadArchives();
|
||||
compiler.Compile();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
36
Wabbajack/Properties/AssemblyInfo.cs
Normal file
36
Wabbajack/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("Wabbajack")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Wabbajack")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2019")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("1649cab3-6f8e-4f2e-844c-931bd4b61233")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
71
Wabbajack/Wabbajack.csproj
Normal file
71
Wabbajack/Wabbajack.csproj
Normal file
@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{1649CAB3-6F8E-4F2E-844C-931BD4B61233}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>Wabbajack</RootNamespace>
|
||||
<AssemblyName>Wabbajack</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="MurmurHash, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\murmurhash.1.0.3\lib\net45\MurmurHash.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Compiler.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<WCFMetadata Include="Connected Services\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SevenZipExtractor\SevenZipExtractor.csproj">
|
||||
<Project>{8aa97f58-5044-4bba-b8d9-a74b6947a660}</Project>
|
||||
<Name>SevenZipExtractor</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Wabbajack.Common\Wabbajack.Common.csproj">
|
||||
<Project>{b3f3fb6e-b9eb-4f49-9875-d78578bc7ae5}</Project>
|
||||
<Name>Wabbajack.Common</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
4
Wabbajack/packages.config
Normal file
4
Wabbajack/packages.config
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="murmurhash" version="1.0.3" targetFramework="net472" />
|
||||
</packages>
|
Loading…
Reference in New Issue
Block a user