Skip to content

Commit

Permalink
Minimalistic hacky example of reading/writing 7zip archives
Browse files Browse the repository at this point in the history
  • Loading branch information
thebrandre committed Feb 11, 2024
0 parents commit 3e66e8c
Show file tree
Hide file tree
Showing 25 changed files with 1,292 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/.vs/
/.idea/
/cmake-build-*/
/out/
46 changes: 46 additions & 0 deletions ArchiveFactory.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#include "ArchiveFactory.h"
#include "ExportGUID.h"

#include <stdexcept>



ArchiveFactory::ArchiveFactory()
{
Handle7zipDLL = LoadLibraryW(L"7zip.dll");
if (!Handle7zipDLL)
throw std::runtime_error("7zip DLL not loaded");

CreateObject = Z7_GET_PROC_ADDRESS(Func_CreateObject, Handle7zipDLL, "CreateObject");

if (!CreateObject)
throw std::runtime_error("CreateObject not found");

}

ArchiveFactory::~ArchiveFactory()
{
FreeLibrary(Handle7zipDLL);
}

CMyComPtr<IInArchive> ArchiveFactory::createIInArchive()
{

CMyComPtr<IInArchive> archive;
if (CreateObject(&CLSID_Format, &IID_IInArchive, (void**)&archive) != S_OK)
{
throw std::runtime_error("CreateObject not found");
}
return archive;

}

CMyComPtr<IOutArchive> ArchiveFactory::createIOutArchive()
{
CMyComPtr<IOutArchive> archive;
if (CreateObject(&CLSID_Format, &IID_IOutArchive, (void**)&archive) != S_OK)
{
throw std::runtime_error("CreateObject not found");
}
return archive;
}
24 changes: 24 additions & 0 deletions ArchiveFactory.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@


#pragma once
#include "7zip/Archive/IArchive.h"
#include "Common/MyCom.h"

class ArchiveFactory{
public:
ArchiveFactory();
ArchiveFactory(const ArchiveFactory&) = delete;
ArchiveFactory(ArchiveFactory&&) noexcept = delete;
ArchiveFactory& operator=(const ArchiveFactory&) = delete;
ArchiveFactory& operator=(ArchiveFactory&&) noexcept = delete;
~ArchiveFactory();

CMyComPtr<IInArchive> createIInArchive();
CMyComPtr<IOutArchive> createIOutArchive();


private:
HMODULE Handle7zipDLL;
Func_CreateObject CreateObject;
};

65 changes: 65 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
cmake_minimum_required (VERSION 3.25)

# Enable Hot Reload for MSVC compilers if supported.
if (POLICY CMP0141)
cmake_policy(SET CMP0141 NEW)
set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<IF:$<AND:$<C_COMPILER_ID:MSVC>,$<CXX_COMPILER_ID:MSVC>>,$<$<CONFIG:Debug,RelWithDebInfo>:EditAndContinue>,$<$<CONFIG:Debug,RelWithDebInfo>:ProgramDatabase>>")
endif()

if (POLICY CMP0077)
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
set(X_VCPKG_APPLOCAL_DEPS_INSTALL ON)
set(VCPKG_APPLOCAL_DEPS_INSTALL ON)
endif()

project ("7zip-examples")

find_package(7zip CONFIG REQUIRED)
find_package(fmt CONFIG REQUIRED)
find_package(Boost REQUIRED)

add_executable (7zip-examples)

target_sources(7zip-examples
PRIVATE
"main.cpp"
"InMemoryArchiveUpdateCallback.h"
"InMemoryArchiveUpdateCallback.cpp"
"ArchiveFactory.h"
"ArchiveFactory.cpp"
"ExportGUID.cpp"
"ExportGUID.h"
"InMemoryArchiveOpenCallback.cpp"
"InMemoryExtractCallback.h"
"InMemoryExtractCallback.cpp"
"StdFileInStream.h"
"StdFileInStream.cpp"
"InMemoryOutStream.h"
"InMemoryOutStream.cpp"
"InMemoryFileSystem.h"
"InMemoryArchive.h"
"InMemoryArchive.cpp"
"InMemoryFileSystem.cpp"
"InMemoryInStream.h"
"InMemoryInStream.cpp"
)

set_property(TARGET 7zip-examples PROPERTY CXX_STANDARD 23)
target_link_libraries(7zip-examples
PRIVATE
7zip::7zip
Boost::boost
fmt::fmt
Bcrypt.lib
)

if (WIN32)
target_compile_definitions(7zip-examples
PRIVATE
UNICODE_
UNICODE
NOMINMAX
_WIN32_WINNT=0x0A00
)
endif()

110 changes: 110 additions & 0 deletions CMakePresets.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
{
"version": 3,
"configurePresets": [
{
"name": "windows-base",
"hidden": true,
"generator": "Ninja",
"binaryDir": "${sourceDir}/out/build/${presetName}",
"installDir": "${sourceDir}/out/install/${presetName}",
"toolchainFile": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake",
"cacheVariables": {
"CMAKE_C_COMPILER": "cl.exe",
"CMAKE_CXX_COMPILER": "cl.exe",
"VCPKG_APPLOCAL_DEPS_INSTALL": {
"type": "BOOL",
"value": "ON"
},
"X_VCPKG_APPLOCAL_DEPS_INSTALL": {
"type": "BOOL",
"value": "ON"
}
},
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Windows"
}
},
{
"name": "x64-debug",
"displayName": "x64 Debug",
"inherits": "windows-base",
"architecture": {
"value": "x64",
"strategy": "external"
},
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
}
},
{
"name": "x64-release",
"displayName": "x64 Release",
"inherits": "x64-debug",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release"
}
},
{
"name": "x86-debug",
"displayName": "x86 Debug",
"inherits": "windows-base",
"architecture": {
"value": "x86",
"strategy": "external"
},
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
}
},
{
"name": "x86-release",
"displayName": "x86 Release",
"inherits": "x86-debug",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release"
}
},
{
"name": "linux-debug",
"displayName": "Linux Debug",
"generator": "Ninja",
"binaryDir": "${sourceDir}/out/build/${presetName}",
"installDir": "${sourceDir}/out/install/${presetName}",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
},
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Linux"
},
"vendor": {
"microsoft.com/VisualStudioRemoteSettings/CMake/1.0": {
"sourceDir": "$env{HOME}/.vs/$ms{projectDirName}"
}
}
},
{
"name": "macos-debug",
"displayName": "macOS Debug",
"generator": "Ninja",
"binaryDir": "${sourceDir}/out/build/${presetName}",
"installDir": "${sourceDir}/out/install/${presetName}",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
},
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Darwin"
},
"vendor": {
"microsoft.com/VisualStudioRemoteSettings/CMake/1.0": {
"sourceDir": "$env{HOME}/.vs/$ms{projectDirName}"
}
}
}
]
}
8 changes: 8 additions & 0 deletions ExportGUID.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#define INITGUID

#include <7zip/ICoder.h>
#include <7zip/IPassword.h>
#include <7zip/Archive/IArchive.h>
#include <7zip/IProgress.h>

#include "ExportGUID.h"
17 changes: 17 additions & 0 deletions ExportGUID.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#pragma once

#define DEFINE_GUID_ARC(name, id) Z7_DEFINE_GUID(name, \
0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, id, 0x00, 0x00);

enum
{
kId_Zip = 1,
kId_BZip2 = 2,
kId_7z = 7,
kId_Xz = 0xC,
kId_Tar = 0xEE,
kId_GZip = 0xEF
};

DEFINE_GUID_ARC(CLSID_Format, kId_7z)

15 changes: 15 additions & 0 deletions InMemoryArchive.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#include "InMemoryArchive.h"

#include <memory>

#include "InMemoryArchiveUpdateCallback.h"
#include "InMemoryFileSystem.h"

CMyComPtr<IArchiveUpdateCallback> InMemoryArchive::getUpdateCallback()
{
return new InMemoryArchiveUpdateCallback(this);
}

InMemoryArchive::InMemoryArchive()
{
}
13 changes: 13 additions & 0 deletions InMemoryArchive.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#pragma once
#include <7zip/Archive/IArchive.h>
#include <Common/MyCom.h>
#include "InMemoryFileSystem.h"

class InMemoryArchive {
public:
CMyComPtr<IArchiveUpdateCallback> getUpdateCallback();

InMemoryArchive();

InMemoryFileSystem FileSystem;
};
35 changes: 35 additions & 0 deletions InMemoryArchiveOpenCallback.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#include "InMemoryArchiveOpenCallback.h"

#include <fmt/format.h>
#include <boost/nowide/convert.hpp>

InMemoryArchiveOpenCallback::InMemoryArchiveOpenCallback() = default;

InMemoryArchiveOpenCallback::InMemoryArchiveOpenCallback(std::u8string Password) : Password(Password)
{}

InMemoryArchiveOpenCallback::~InMemoryArchiveOpenCallback()
= default;

Z7_COM7F_IMF(InMemoryArchiveOpenCallback::SetTotal(const UInt64* files, const UInt64* bytes))
{
fmt::print("SetTotal {} files and {} bytes.", files != nullptr ? *files : 0, bytes != nullptr ? *bytes : 0);

return S_OK;
}

Z7_COM7F_IMF(InMemoryArchiveOpenCallback::SetCompleted(const UInt64* files, const UInt64* bytes))
{
fmt::print("SetCompleted {} files and {} bytes.", files != nullptr ? *files : 0, bytes != nullptr ? *bytes : 0);
return S_OK;
}

Z7_COM7F_IMF(InMemoryArchiveOpenCallback::CryptoGetTextPassword(BSTR* password))
{
PasswordRequired = true;
if (!Password)
return E_ABORT;

return StringToBstr(boost::nowide::widen(Password.value()).c_str(), password);
}

27 changes: 27 additions & 0 deletions InMemoryArchiveOpenCallback.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#pragma once
#include <7zip/Archive/IArchive.h>
#include <7zip/IPassword.h>
#include <Common/MyCom.h>
#include <string>
#include <optional>

class InMemoryArchiveOpenCallback Z7_final :
public IArchiveOpenCallback,
public ICryptoGetTextPassword,
public CMyUnknownImp
{
Z7_IFACES_IMP_UNK_2(IArchiveOpenCallback, ICryptoGetTextPassword)
public:
explicit InMemoryArchiveOpenCallback();
explicit InMemoryArchiveOpenCallback(std::u8string Password);
InMemoryArchiveOpenCallback(const InMemoryArchiveOpenCallback& Other) = delete;
InMemoryArchiveOpenCallback(InMemoryArchiveOpenCallback&& Other) noexcept = delete;
InMemoryArchiveOpenCallback& operator=(const InMemoryArchiveOpenCallback& Other) = delete;
InMemoryArchiveOpenCallback& operator=(InMemoryArchiveOpenCallback&& Other) noexcept = delete;
virtual ~InMemoryArchiveOpenCallback();

private:
std::optional<std::u8string> Password;
bool PasswordRequired{};
};

Loading

0 comments on commit 3e66e8c

Please sign in to comment.