From 6e496381d819d5ca1f11e73f6ecea17733a4a7d6 Mon Sep 17 00:00:00 2001 From: DavidXanatos Date: Sat, 12 Nov 2022 10:45:35 +0100 Subject: [PATCH] 1.6.0 --- CHANGELOG.md | 15 + .../MiscHelpers/Archive/7z/C/Types.h | 254 +++++++++ .../Archive/7z/CPP/7zip/Archive/IArchive.h | 234 ++++++++ .../MiscHelpers/Archive/7z/CPP/7zip/ICoder.h | 186 +++++++ .../MiscHelpers/Archive/7z/CPP/7zip/IDecl.h | 15 + .../Archive/7z/CPP/7zip/IPassword.h | 24 + .../Archive/7z/CPP/7zip/IProgress.h | 33 ++ .../MiscHelpers/Archive/7z/CPP/7zip/IStream.h | 58 ++ .../MiscHelpers/Archive/7z/CPP/7zip/PropID.h | 76 +++ .../MiscHelpers/Archive/7z/CPP/Common/Defs.h | 20 + .../MiscHelpers/Archive/7z/CPP/Common/MyCom.h | 225 ++++++++ .../Archive/7z/CPP/Common/MyInitGuid.h | 22 + .../Archive/7z/CPP/Common/MyUnknown.h | 13 + .../Archive/7z/CPP/Common/MyWindows.cpp | 109 ++++ .../Archive/7z/CPP/Common/MyWindows.h | 204 +++++++ .../Archive/7z/CPP/Common/NewHandler.cpp | 116 ++++ .../Archive/7z/CPP/Common/NewHandler.h | 16 + .../MiscHelpers/Archive/7z/CPP/Common/Types.h | 11 + .../MiscHelpers/Archive/7z/CPP/Windows/Defs.h | 17 + .../Archive/7z/CPP/Windows/PropVariant.cpp | 243 +++++++++ .../Archive/7z/CPP/Windows/PropVariant.h | 56 ++ .../Archive/7z/CPP/Windows/StdAfx.h | 9 + SandboxiePlus/MiscHelpers/Archive/Archive.cpp | 503 ++++++++++++++++++ SandboxiePlus/MiscHelpers/Archive/Archive.h | 124 +++++ .../MiscHelpers/Archive/ArchiveExtractor.cpp | 103 ++++ .../MiscHelpers/Archive/ArchiveExtractor.h | 34 ++ .../MiscHelpers/Archive/ArchiveFS.cpp | 284 ++++++++++ SandboxiePlus/MiscHelpers/Archive/ArchiveFS.h | 84 +++ .../MiscHelpers/Archive/ArchiveHelper.cpp | 156 ++++++ .../MiscHelpers/Archive/ArchiveHelper.h | 85 +++ SandboxiePlus/MiscHelpers/Archive/ArchiveIO.h | 84 +++ .../MiscHelpers/Archive/ArchiveInterface.cpp | 193 +++++++ .../MiscHelpers/Archive/ArchiveInterface.h | 114 ++++ .../MiscHelpers/Archive/ArchiveOpener.cpp | 53 ++ .../MiscHelpers/Archive/ArchiveOpener.h | 29 + .../MiscHelpers/Archive/ArchiveThread.cpp | 419 +++++++++++++++ .../MiscHelpers/Archive/ArchiveThread.h | 147 +++++ .../MiscHelpers/Archive/ArchiveUpdater.cpp | 106 ++++ .../MiscHelpers/Archive/ArchiveUpdater.h | 38 ++ .../MiscHelpers/Archive/CachedArchive.cpp | 37 ++ .../MiscHelpers/Archive/CachedArchive.h | 22 + .../MiscHelpers/Archive/SplitFile.cpp | 186 +++++++ SandboxiePlus/MiscHelpers/Archive/SplitFile.h | 32 ++ SandboxiePlus/MiscHelpers/Common/Finder.cpp | 2 +- .../MiscHelpers/Common/MT/ThreadLock.cpp | 37 ++ .../MiscHelpers/Common/MT/ThreadLock.h | 28 + .../MiscHelpers/Common/ProgressDialog.h | 2 + SandboxiePlus/MiscHelpers/MiscHelpers.pri | 28 +- SandboxiePlus/MiscHelpers/MiscHelpers.vcxproj | 23 + .../MiscHelpers/MiscHelpers.vcxproj.filters | 75 +++ SandboxiePlus/SandMan/SandMan.cpp | 64 ++- SandboxiePlus/SandMan/SandMan.h | 2 + SandboxiePlus/SandMan/SbiePlusAPI.cpp | 156 ++++++ SandboxiePlus/SandMan/SbiePlusAPI.h | 16 + SandboxiePlus/SandMan/Views/SbieView.cpp | 22 +- SandboxiePlus/SandMan/Views/SbieView.h | 1 + 56 files changed, 5237 insertions(+), 8 deletions(-) create mode 100644 SandboxiePlus/MiscHelpers/Archive/7z/C/Types.h create mode 100644 SandboxiePlus/MiscHelpers/Archive/7z/CPP/7zip/Archive/IArchive.h create mode 100644 SandboxiePlus/MiscHelpers/Archive/7z/CPP/7zip/ICoder.h create mode 100644 SandboxiePlus/MiscHelpers/Archive/7z/CPP/7zip/IDecl.h create mode 100644 SandboxiePlus/MiscHelpers/Archive/7z/CPP/7zip/IPassword.h create mode 100644 SandboxiePlus/MiscHelpers/Archive/7z/CPP/7zip/IProgress.h create mode 100644 SandboxiePlus/MiscHelpers/Archive/7z/CPP/7zip/IStream.h create mode 100644 SandboxiePlus/MiscHelpers/Archive/7z/CPP/7zip/PropID.h create mode 100644 SandboxiePlus/MiscHelpers/Archive/7z/CPP/Common/Defs.h create mode 100644 SandboxiePlus/MiscHelpers/Archive/7z/CPP/Common/MyCom.h create mode 100644 SandboxiePlus/MiscHelpers/Archive/7z/CPP/Common/MyInitGuid.h create mode 100644 SandboxiePlus/MiscHelpers/Archive/7z/CPP/Common/MyUnknown.h create mode 100644 SandboxiePlus/MiscHelpers/Archive/7z/CPP/Common/MyWindows.cpp create mode 100644 SandboxiePlus/MiscHelpers/Archive/7z/CPP/Common/MyWindows.h create mode 100644 SandboxiePlus/MiscHelpers/Archive/7z/CPP/Common/NewHandler.cpp create mode 100644 SandboxiePlus/MiscHelpers/Archive/7z/CPP/Common/NewHandler.h create mode 100644 SandboxiePlus/MiscHelpers/Archive/7z/CPP/Common/Types.h create mode 100644 SandboxiePlus/MiscHelpers/Archive/7z/CPP/Windows/Defs.h create mode 100644 SandboxiePlus/MiscHelpers/Archive/7z/CPP/Windows/PropVariant.cpp create mode 100644 SandboxiePlus/MiscHelpers/Archive/7z/CPP/Windows/PropVariant.h create mode 100644 SandboxiePlus/MiscHelpers/Archive/7z/CPP/Windows/StdAfx.h create mode 100644 SandboxiePlus/MiscHelpers/Archive/Archive.cpp create mode 100644 SandboxiePlus/MiscHelpers/Archive/Archive.h create mode 100644 SandboxiePlus/MiscHelpers/Archive/ArchiveExtractor.cpp create mode 100644 SandboxiePlus/MiscHelpers/Archive/ArchiveExtractor.h create mode 100644 SandboxiePlus/MiscHelpers/Archive/ArchiveFS.cpp create mode 100644 SandboxiePlus/MiscHelpers/Archive/ArchiveFS.h create mode 100644 SandboxiePlus/MiscHelpers/Archive/ArchiveHelper.cpp create mode 100644 SandboxiePlus/MiscHelpers/Archive/ArchiveHelper.h create mode 100644 SandboxiePlus/MiscHelpers/Archive/ArchiveIO.h create mode 100644 SandboxiePlus/MiscHelpers/Archive/ArchiveInterface.cpp create mode 100644 SandboxiePlus/MiscHelpers/Archive/ArchiveInterface.h create mode 100644 SandboxiePlus/MiscHelpers/Archive/ArchiveOpener.cpp create mode 100644 SandboxiePlus/MiscHelpers/Archive/ArchiveOpener.h create mode 100644 SandboxiePlus/MiscHelpers/Archive/ArchiveThread.cpp create mode 100644 SandboxiePlus/MiscHelpers/Archive/ArchiveThread.h create mode 100644 SandboxiePlus/MiscHelpers/Archive/ArchiveUpdater.cpp create mode 100644 SandboxiePlus/MiscHelpers/Archive/ArchiveUpdater.h create mode 100644 SandboxiePlus/MiscHelpers/Archive/CachedArchive.cpp create mode 100644 SandboxiePlus/MiscHelpers/Archive/CachedArchive.h create mode 100644 SandboxiePlus/MiscHelpers/Archive/SplitFile.cpp create mode 100644 SandboxiePlus/MiscHelpers/Archive/SplitFile.h create mode 100644 SandboxiePlus/MiscHelpers/Common/MT/ThreadLock.cpp create mode 100644 SandboxiePlus/MiscHelpers/Common/MT/ThreadLock.h diff --git a/CHANGELOG.md b/CHANGELOG.md index 6388a520..e9c4ebc0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,21 @@ This project adheres to [Semantic Versioning](http://semver.org/). + +## [1.6.0 / 5.61.0] - 2022-??-?? + +### Added +- added ability to import/export boxes into 7z files + +### Changed +- restructured the box context menu a bit +- sandman translations are now compressed and located in translations.7z + + + + + + ## [1.5.3 / 5.60.3] - 2022-11-?? ### Added diff --git a/SandboxiePlus/MiscHelpers/Archive/7z/C/Types.h b/SandboxiePlus/MiscHelpers/Archive/7z/C/Types.h new file mode 100644 index 00000000..7732c240 --- /dev/null +++ b/SandboxiePlus/MiscHelpers/Archive/7z/C/Types.h @@ -0,0 +1,254 @@ +/* Types.h -- Basic types +2010-10-09 : Igor Pavlov : Public domain */ + +#ifndef __7Z_TYPES_H +#define __7Z_TYPES_H + +#include + +#ifdef _WIN32 +#include +#endif + +#ifndef EXTERN_C_BEGIN +#ifdef __cplusplus +#define EXTERN_C_BEGIN extern "C" { +#define EXTERN_C_END } +#else +#define EXTERN_C_BEGIN +#define EXTERN_C_END +#endif +#endif + +EXTERN_C_BEGIN + +#define SZ_OK 0 + +#define SZ_ERROR_DATA 1 +#define SZ_ERROR_MEM 2 +#define SZ_ERROR_CRC 3 +#define SZ_ERROR_UNSUPPORTED 4 +#define SZ_ERROR_PARAM 5 +#define SZ_ERROR_INPUT_EOF 6 +#define SZ_ERROR_OUTPUT_EOF 7 +#define SZ_ERROR_READ 8 +#define SZ_ERROR_WRITE 9 +#define SZ_ERROR_PROGRESS 10 +#define SZ_ERROR_FAIL 11 +#define SZ_ERROR_THREAD 12 + +#define SZ_ERROR_ARCHIVE 16 +#define SZ_ERROR_NO_ARCHIVE 17 + +typedef int SRes; + +#ifdef _WIN32 +typedef DWORD WRes; +#else +typedef int WRes; +#endif + +#ifndef RINOK +#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } +#endif + +typedef unsigned char Byte; +typedef short Int16; +typedef unsigned short UInt16; + +#ifdef _LZMA_UINT32_IS_ULONG +typedef long Int32; +typedef unsigned long UInt32; +#else +typedef int Int32; +typedef unsigned int UInt32; +#endif + +#ifdef _SZ_NO_INT_64 + +/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers. + NOTES: Some code will work incorrectly in that case! */ + +typedef long Int64; +typedef unsigned long UInt64; + +#else + +#if defined(_MSC_VER) || defined(__BORLANDC__) +typedef __int64 Int64; +typedef unsigned __int64 UInt64; +#define UINT64_CONST(n) n +#else +typedef long long int Int64; +typedef unsigned long long int UInt64; +#define UINT64_CONST(n) n ## ULL +#endif + +#endif + +#ifdef _LZMA_NO_SYSTEM_SIZE_T +typedef UInt32 SizeT; +#else +typedef size_t SizeT; +#endif + +typedef int Bool; +#define True 1 +#define False 0 + + +#ifdef _WIN32 +#define MY_STD_CALL __stdcall +#else +#define MY_STD_CALL +#endif + +#ifdef _MSC_VER + +#if _MSC_VER >= 1300 +#define MY_NO_INLINE __declspec(noinline) +#else +#define MY_NO_INLINE +#endif + +#define MY_CDECL __cdecl +#define MY_FAST_CALL __fastcall + +#else + +#define MY_CDECL +#define MY_FAST_CALL + +#endif + + +/* The following interfaces use first parameter as pointer to structure */ + +typedef struct +{ + Byte (*Read)(void *p); /* reads one byte, returns 0 in case of EOF or error */ +} IByteIn; + +typedef struct +{ + void (*Write)(void *p, Byte b); +} IByteOut; + +typedef struct +{ + SRes (*Read)(void *p, void *buf, size_t *size); + /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. + (output(*size) < input(*size)) is allowed */ +} ISeqInStream; + +/* it can return SZ_ERROR_INPUT_EOF */ +SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size); +SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType); +SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf); + +typedef struct +{ + size_t (*Write)(void *p, const void *buf, size_t size); + /* Returns: result - the number of actually written bytes. + (result < size) means error */ +} ISeqOutStream; + +typedef enum +{ + SZ_SEEK_SET = 0, + SZ_SEEK_CUR = 1, + SZ_SEEK_END = 2 +} ESzSeek; + +typedef struct +{ + SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */ + SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); +} ISeekInStream; + +typedef struct +{ + SRes (*Look)(void *p, const void **buf, size_t *size); + /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. + (output(*size) > input(*size)) is not allowed + (output(*size) < input(*size)) is allowed */ + SRes (*Skip)(void *p, size_t offset); + /* offset must be <= output(*size) of Look */ + + SRes (*Read)(void *p, void *buf, size_t *size); + /* reads directly (without buffer). It's same as ISeqInStream::Read */ + SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); +} ILookInStream; + +SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size); +SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset); + +/* reads via ILookInStream::Read */ +SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType); +SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size); + +#define LookToRead_BUF_SIZE (1 << 14) + +typedef struct +{ + ILookInStream s; + ISeekInStream *realStream; + size_t pos; + size_t size; + Byte buf[LookToRead_BUF_SIZE]; +} CLookToRead; + +void LookToRead_CreateVTable(CLookToRead *p, int lookahead); +void LookToRead_Init(CLookToRead *p); + +typedef struct +{ + ISeqInStream s; + ILookInStream *realStream; +} CSecToLook; + +void SecToLook_CreateVTable(CSecToLook *p); + +typedef struct +{ + ISeqInStream s; + ILookInStream *realStream; +} CSecToRead; + +void SecToRead_CreateVTable(CSecToRead *p); + +typedef struct +{ + SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize); + /* Returns: result. (result != SZ_OK) means break. + Value (UInt64)(Int64)-1 for size means unknown value. */ +} ICompressProgress; + +typedef struct +{ + void *(*Alloc)(void *p, size_t size); + void (*Free)(void *p, void *address); /* address can be 0 */ +} ISzAlloc; + +#define IAlloc_Alloc(p, size) (p)->Alloc((p), size) +#define IAlloc_Free(p, a) (p)->Free((p), a) + +#ifdef _WIN32 + +#define CHAR_PATH_SEPARATOR '\\' +#define WCHAR_PATH_SEPARATOR L'\\' +#define STRING_PATH_SEPARATOR "\\" +#define WSTRING_PATH_SEPARATOR L"\\" + +#else + +#define CHAR_PATH_SEPARATOR '/' +#define WCHAR_PATH_SEPARATOR L'/' +#define STRING_PATH_SEPARATOR "/" +#define WSTRING_PATH_SEPARATOR L"/" + +#endif + +EXTERN_C_END + +#endif diff --git a/SandboxiePlus/MiscHelpers/Archive/7z/CPP/7zip/Archive/IArchive.h b/SandboxiePlus/MiscHelpers/Archive/7z/CPP/7zip/Archive/IArchive.h new file mode 100644 index 00000000..85320276 --- /dev/null +++ b/SandboxiePlus/MiscHelpers/Archive/7z/CPP/7zip/Archive/IArchive.h @@ -0,0 +1,234 @@ +// IArchive.h + +#ifndef __IARCHIVE_H +#define __IARCHIVE_H + +#include "../IProgress.h" +#include "../IStream.h" +#include "../PropID.h" + +#define ARCHIVE_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 6, x) +#define ARCHIVE_INTERFACE(i, x) ARCHIVE_INTERFACE_SUB(i, IUnknown, x) + +namespace NFileTimeType +{ + enum EEnum + { + kWindows, + kUnix, + kDOS + }; +} + +namespace NArchive +{ + enum + { + kName = 0, + kClassID, + kExtension, + kAddExtension, + kUpdate, + kKeepName, + kStartSignature, + kFinishSignature, + kAssociate + }; + + namespace NExtract + { + namespace NAskMode + { + enum + { + kExtract = 0, + kTest, + kSkip + }; + } + namespace NOperationResult + { + enum + { + kOK = 0, + kUnSupportedMethod, + kDataError, + kCRCError + }; + } + } + namespace NUpdate + { + namespace NOperationResult + { + enum + { + kOK = 0, + kError + }; + } + } +} + +#define INTERFACE_IArchiveOpenCallback(x) \ + STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes) x; \ + STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes) x; \ + +ARCHIVE_INTERFACE(IArchiveOpenCallback, 0x10) +{ + INTERFACE_IArchiveOpenCallback(PURE); +}; + + +#define INTERFACE_IArchiveExtractCallback(x) \ + INTERFACE_IProgress(x) \ + STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) x; \ + STDMETHOD(PrepareOperation)(Int32 askExtractMode) x; \ + STDMETHOD(SetOperationResult)(Int32 resultEOperationResult) x; \ + +ARCHIVE_INTERFACE_SUB(IArchiveExtractCallback, IProgress, 0x20) +{ + INTERFACE_IArchiveExtractCallback(PURE) +}; + + +#define INTERFACE_IArchiveOpenVolumeCallback(x) \ + STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value) x; \ + STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream) x; \ + +ARCHIVE_INTERFACE(IArchiveOpenVolumeCallback, 0x30) +{ + INTERFACE_IArchiveOpenVolumeCallback(PURE); +}; + + +ARCHIVE_INTERFACE(IInArchiveGetStream, 0x40) +{ + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream) PURE; +}; + + +ARCHIVE_INTERFACE(IArchiveOpenSetSubArchiveName, 0x50) +{ + STDMETHOD(SetSubArchiveName)(const wchar_t *name) PURE; +}; + + +/* +IInArchive::Extract: + indices must be sorted + numItems = 0xFFFFFFFF means "all files" + testMode != 0 means "test files without writing to outStream" +*/ + +#define INTERFACE_IInArchive(x) \ + STDMETHOD(Open)(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback) x; \ + STDMETHOD(Close)() x; \ + STDMETHOD(GetNumberOfItems)(UInt32 *numItems) x; \ + STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \ + STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) x; \ + STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value) x; \ + STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties) x; \ + STDMETHOD(GetPropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; \ + STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProperties) x; \ + STDMETHOD(GetArchivePropertyInfo)(UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) x; + +ARCHIVE_INTERFACE(IInArchive, 0x60) +{ + INTERFACE_IInArchive(PURE) +}; + +ARCHIVE_INTERFACE(IArchiveOpenSeq, 0x61) +{ + STDMETHOD(OpenSeq)(ISequentialInStream *stream) PURE; +}; + +#define INTERFACE_IArchiveUpdateCallback(x) \ + INTERFACE_IProgress(x); \ + STDMETHOD(GetUpdateItemInfo)(UInt32 index, \ + Int32 *newData, /*1 - new data, 0 - old data */ \ + Int32 *newProperties, /* 1 - new properties, 0 - old properties */ \ + UInt32 *indexInArchive /* -1 if there is no in archive, or if doesn't matter */ \ + ) x; \ + STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) x; \ + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream) x; \ + STDMETHOD(SetOperationResult)(Int32 operationResult) x; \ + +ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback, IProgress, 0x80) +{ + INTERFACE_IArchiveUpdateCallback(PURE); +}; + +#define INTERFACE_IArchiveUpdateCallback2(x) \ + INTERFACE_IArchiveUpdateCallback(x) \ + STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size) x; \ + STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream) x; \ + +ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback2, IArchiveUpdateCallback, 0x82) +{ + INTERFACE_IArchiveUpdateCallback2(PURE); +}; + + +#define INTERFACE_IOutArchive(x) \ + STDMETHOD(UpdateItems)(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback) x; \ + STDMETHOD(GetFileTimeType)(UInt32 *type) x; + +ARCHIVE_INTERFACE(IOutArchive, 0xA0) +{ + INTERFACE_IOutArchive(PURE) +}; + + +ARCHIVE_INTERFACE(ISetProperties, 0x03) +{ + STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) PURE; +}; + + +#define IMP_IInArchive_GetProp(k) \ + (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \ + { if(index >= sizeof(k) / sizeof(k[0])) return E_INVALIDARG; \ + const STATPROPSTG &srcItem = k[index]; \ + *propID = srcItem.propid; *varType = srcItem.vt; *name = 0; return S_OK; } \ + +#define IMP_IInArchive_GetProp_WITH_NAME(k) \ + (UInt32 index, BSTR *name, PROPID *propID, VARTYPE *varType) \ + { if(index >= sizeof(k) / sizeof(k[0])) return E_INVALIDARG; \ + const STATPROPSTG &srcItem = k[index]; \ + *propID = srcItem.propid; *varType = srcItem.vt; \ + if (srcItem.lpwstrName == 0) *name = 0; else *name = ::SysAllocString(srcItem.lpwstrName); return S_OK; } \ + +#define IMP_IInArchive_Props \ + STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) \ + { *numProperties = sizeof(kProps) / sizeof(kProps[0]); return S_OK; } \ + STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp(kProps) + +#define IMP_IInArchive_Props_WITH_NAME \ + STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) \ + { *numProperties = sizeof(kProps) / sizeof(kProps[0]); return S_OK; } \ + STDMETHODIMP CHandler::GetPropertyInfo IMP_IInArchive_GetProp_WITH_NAME(kProps) + + +#define IMP_IInArchive_ArcProps \ + STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \ + { *numProperties = sizeof(kArcProps) / sizeof(kArcProps[0]); return S_OK; } \ + STDMETHODIMP CHandler::GetArchivePropertyInfo IMP_IInArchive_GetProp(kArcProps) + +#define IMP_IInArchive_ArcProps_WITH_NAME \ + STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \ + { *numProperties = sizeof(kArcProps) / sizeof(kArcProps[0]); return S_OK; } \ + STDMETHODIMP CHandler::GetArchivePropertyInfo IMP_IInArchive_GetProp_WITH_NAME(kArcProps) + +#define IMP_IInArchive_ArcProps_NO_Table \ + STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) \ + { *numProperties = 0; return S_OK; } \ + STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32, BSTR *, PROPID *, VARTYPE *) \ + { return E_NOTIMPL; } \ + +#define IMP_IInArchive_ArcProps_NO \ + IMP_IInArchive_ArcProps_NO_Table \ + STDMETHODIMP CHandler::GetArchiveProperty(PROPID, PROPVARIANT *value) \ + { value->vt = VT_EMPTY; return S_OK; } + +#endif diff --git a/SandboxiePlus/MiscHelpers/Archive/7z/CPP/7zip/ICoder.h b/SandboxiePlus/MiscHelpers/Archive/7z/CPP/7zip/ICoder.h new file mode 100644 index 00000000..a518de46 --- /dev/null +++ b/SandboxiePlus/MiscHelpers/Archive/7z/CPP/7zip/ICoder.h @@ -0,0 +1,186 @@ +// ICoder.h + +#ifndef __ICODER_H +#define __ICODER_H + +#include "IStream.h" + +#define CODER_INTERFACE(i, x) DECL_INTERFACE(i, 4, x) + +CODER_INTERFACE(ICompressProgressInfo, 0x04) +{ + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize) PURE; +}; + +CODER_INTERFACE(ICompressCoder, 0x05) +{ + STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, + ICompressProgressInfo *progress) PURE; +}; + +CODER_INTERFACE(ICompressCoder2, 0x18) +{ + STDMETHOD(Code)(ISequentialInStream **inStreams, const UInt64 **inSizes, UInt32 numInStreams, + ISequentialOutStream **outStreams, const UInt64 **outSizes, UInt32 numOutStreams, + ICompressProgressInfo *progress) PURE; +}; + +namespace NCoderPropID +{ + enum EEnum + { + kDefaultProp = 0, + kDictionarySize, + kUsedMemorySize, + kOrder, + kBlockSize, + kPosStateBits, + kLitContextBits, + kLitPosBits, + kNumFastBytes, + kMatchFinder, + kMatchFinderCycles, + kNumPasses, + kAlgorithm, + kNumThreads, + kEndMarker + }; +} + +CODER_INTERFACE(ICompressSetCoderProperties, 0x20) +{ + STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps) PURE; +}; + +/* +CODER_INTERFACE(ICompressSetCoderProperties, 0x21) +{ + STDMETHOD(SetDecoderProperties)(ISequentialInStream *inStream) PURE; +}; +*/ + +CODER_INTERFACE(ICompressSetDecoderProperties2, 0x22) +{ + STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size) PURE; +}; + +CODER_INTERFACE(ICompressWriteCoderProperties, 0x23) +{ + STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream) PURE; +}; + +CODER_INTERFACE(ICompressGetInStreamProcessedSize, 0x24) +{ + STDMETHOD(GetInStreamProcessedSize)(UInt64 *value) PURE; +}; + +CODER_INTERFACE(ICompressSetCoderMt, 0x25) +{ + STDMETHOD(SetNumberOfThreads)(UInt32 numThreads) PURE; +}; + +CODER_INTERFACE(ICompressGetSubStreamSize, 0x30) +{ + STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value) PURE; +}; + +CODER_INTERFACE(ICompressSetInStream, 0x31) +{ + STDMETHOD(SetInStream)(ISequentialInStream *inStream) PURE; + STDMETHOD(ReleaseInStream)() PURE; +}; + +CODER_INTERFACE(ICompressSetOutStream, 0x32) +{ + STDMETHOD(SetOutStream)(ISequentialOutStream *outStream) PURE; + STDMETHOD(ReleaseOutStream)() PURE; +}; + +CODER_INTERFACE(ICompressSetInStreamSize, 0x33) +{ + STDMETHOD(SetInStreamSize)(const UInt64 *inSize) PURE; +}; + +CODER_INTERFACE(ICompressSetOutStreamSize, 0x34) +{ + STDMETHOD(SetOutStreamSize)(const UInt64 *outSize) PURE; +}; + +CODER_INTERFACE(ICompressSetBufSize, 0x35) +{ + STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size) PURE; + STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size) PURE; +}; + +CODER_INTERFACE(ICompressFilter, 0x40) +{ + STDMETHOD(Init)() PURE; + STDMETHOD_(UInt32, Filter)(Byte *data, UInt32 size) PURE; + // Filter converts as most as possible bytes + // Filter return outSize (UInt32) + // if (outSize <= size): Filter have converted outSize bytes + // if (outSize > size): Filter have not converted anything. + // and it needs at least outSize bytes to convert one block + // (it's for crypto block algorithms). +}; + +CODER_INTERFACE(ICompressCodecsInfo, 0x60) +{ + STDMETHOD(GetNumberOfMethods)(UInt32 *numMethods) PURE; + STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) PURE; + STDMETHOD(CreateDecoder)(UInt32 index, const GUID *iid, void **coder) PURE; + STDMETHOD(CreateEncoder)(UInt32 index, const GUID *iid, void **coder) PURE; +}; +CODER_INTERFACE(ISetCompressCodecsInfo, 0x61) +{ + STDMETHOD(SetCompressCodecsInfo)(ICompressCodecsInfo *compressCodecsInfo) PURE; +}; + +CODER_INTERFACE(ICryptoProperties, 0x80) +{ + STDMETHOD(SetKey)(const Byte *data, UInt32 size) PURE; + STDMETHOD(SetInitVector)(const Byte *data, UInt32 size) PURE; +}; + +/* +CODER_INTERFACE(ICryptoResetSalt, 0x88) +{ + STDMETHOD(ResetSalt)() PURE; +}; +*/ + +CODER_INTERFACE(ICryptoResetInitVector, 0x8C) +{ + STDMETHOD(ResetInitVector)() PURE; +}; + +CODER_INTERFACE(ICryptoSetPassword, 0x90) +{ + STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size) PURE; +}; + +CODER_INTERFACE(ICryptoSetCRC, 0xA0) +{ + STDMETHOD(CryptoSetCRC)(UInt32 crc) PURE; +}; + +////////////////////// +// It's for DLL file +namespace NMethodPropID +{ + enum EEnum + { + kID, + kName, + kDecoder, + kEncoder, + kInStreams, + kOutStreams, + kDescription, + kDecoderIsAssigned, + kEncoderIsAssigned + }; +} + +#endif diff --git a/SandboxiePlus/MiscHelpers/Archive/7z/CPP/7zip/IDecl.h b/SandboxiePlus/MiscHelpers/Archive/7z/CPP/7zip/IDecl.h new file mode 100644 index 00000000..8316eb3a --- /dev/null +++ b/SandboxiePlus/MiscHelpers/Archive/7z/CPP/7zip/IDecl.h @@ -0,0 +1,15 @@ +// IDecl.h + +#ifndef __IDECL_H +#define __IDECL_H + +#include "../Common/MyUnknown.h" + +#define DECL_INTERFACE_SUB(i, base, groupId, subId) \ +DEFINE_GUID(IID_ ## i, \ +0x23170F69, 0x40C1, 0x278A, 0, 0, 0, (groupId), 0, (subId), 0, 0); \ +struct i: public base + +#define DECL_INTERFACE(i, groupId, subId) DECL_INTERFACE_SUB(i, IUnknown, groupId, subId) + +#endif diff --git a/SandboxiePlus/MiscHelpers/Archive/7z/CPP/7zip/IPassword.h b/SandboxiePlus/MiscHelpers/Archive/7z/CPP/7zip/IPassword.h new file mode 100644 index 00000000..3ca7b090 --- /dev/null +++ b/SandboxiePlus/MiscHelpers/Archive/7z/CPP/7zip/IPassword.h @@ -0,0 +1,24 @@ +// IPassword.h + +#ifndef __IPASSWORD_H +#define __IPASSWORD_H + +#include "../Common/MyUnknown.h" +#include "../Common/Types.h" + +#include "IDecl.h" + +#define PASSWORD_INTERFACE(i, x) DECL_INTERFACE(i, 5, x) + +PASSWORD_INTERFACE(ICryptoGetTextPassword, 0x10) +{ + STDMETHOD(CryptoGetTextPassword)(BSTR *password) PURE; +}; + +PASSWORD_INTERFACE(ICryptoGetTextPassword2, 0x11) +{ + STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password) PURE; +}; + +#endif + diff --git a/SandboxiePlus/MiscHelpers/Archive/7z/CPP/7zip/IProgress.h b/SandboxiePlus/MiscHelpers/Archive/7z/CPP/7zip/IProgress.h new file mode 100644 index 00000000..d6093f17 --- /dev/null +++ b/SandboxiePlus/MiscHelpers/Archive/7z/CPP/7zip/IProgress.h @@ -0,0 +1,33 @@ +// Interface/IProgress.h + +#ifndef __IPROGRESS_H +#define __IPROGRESS_H + +#include "../Common/MyUnknown.h" +#include "../Common/Types.h" + +#include "IDecl.h" + +#define INTERFACE_IProgress(x) \ + STDMETHOD(SetTotal)(UInt64 total) x; \ + STDMETHOD(SetCompleted)(const UInt64 *completeValue) x; \ + +DECL_INTERFACE(IProgress, 0, 5) +{ + INTERFACE_IProgress(PURE) +}; + +/* +// {23170F69-40C1-278A-0000-000000050002} +DEFINE_GUID(IID_IProgress2, +0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x02); +MIDL_INTERFACE("23170F69-40C1-278A-0000-000000050002") +IProgress2: public IUnknown +{ +public: + STDMETHOD(SetTotal)(const UInt64 *total) PURE; + STDMETHOD(SetCompleted)(const UInt64 *completeValue) PURE; +}; +*/ + +#endif diff --git a/SandboxiePlus/MiscHelpers/Archive/7z/CPP/7zip/IStream.h b/SandboxiePlus/MiscHelpers/Archive/7z/CPP/7zip/IStream.h new file mode 100644 index 00000000..165e8baa --- /dev/null +++ b/SandboxiePlus/MiscHelpers/Archive/7z/CPP/7zip/IStream.h @@ -0,0 +1,58 @@ +// IStream.h + +#ifndef __ISTREAM_H +#define __ISTREAM_H + +#include "../Common/MyUnknown.h" +#include "../Common/Types.h" + +#include "IDecl.h" + +#define STREAM_INTERFACE_SUB(i, base, x) DECL_INTERFACE_SUB(i, base, 3, x) +#define STREAM_INTERFACE(i, x) STREAM_INTERFACE_SUB(i, IUnknown, x) + +STREAM_INTERFACE(ISequentialInStream, 0x01) +{ + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) PURE; + /* + 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 + */ +}; + +STREAM_INTERFACE(ISequentialOutStream, 0x02) +{ + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) PURE; + /* + 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 + */ +}; + +STREAM_INTERFACE_SUB(IInStream, ISequentialInStream, 0x03) +{ + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE; +}; + +STREAM_INTERFACE_SUB(IOutStream, ISequentialOutStream, 0x04) +{ + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) PURE; + STDMETHOD(SetSize)(UInt64 newSize) PURE; +}; + +STREAM_INTERFACE(IStreamGetSize, 0x06) +{ + STDMETHOD(GetSize)(UInt64 *size) PURE; +}; + +STREAM_INTERFACE(IOutStreamFlush, 0x07) +{ + STDMETHOD(Flush)() PURE; +}; + +#endif diff --git a/SandboxiePlus/MiscHelpers/Archive/7z/CPP/7zip/PropID.h b/SandboxiePlus/MiscHelpers/Archive/7z/CPP/7zip/PropID.h new file mode 100644 index 00000000..8f888526 --- /dev/null +++ b/SandboxiePlus/MiscHelpers/Archive/7z/CPP/7zip/PropID.h @@ -0,0 +1,76 @@ +// PropID.h + +#ifndef __7ZIP_PROPID_H +#define __7ZIP_PROPID_H + +enum +{ + kpidNoProperty = 0, + kpidMainSubfile = 1, + kpidHandlerItemIndex = 2, + kpidPath, + kpidName, + kpidExtension, + kpidIsDir, + kpidSize, + kpidPackSize, + kpidAttrib, + kpidCTime, + kpidATime, + kpidMTime, + kpidSolid, + kpidCommented, + kpidEncrypted, + kpidSplitBefore, + kpidSplitAfter, + kpidDictionarySize, + kpidCRC, + kpidType, + kpidIsAnti, + kpidMethod, + kpidHostOS, + kpidFileSystem, + kpidUser, + kpidGroup, + kpidBlock, + kpidComment, + kpidPosition, + kpidPrefix, + kpidNumSubDirs, + kpidNumSubFiles, + kpidUnpackVer, + kpidVolume, + kpidIsVolume, + kpidOffset, + kpidLinks, + kpidNumBlocks, + kpidNumVolumes, + kpidTimeType, + kpidBit64, + kpidBigEndian, + kpidCpu, + kpidPhySize, + kpidHeadersSize, + kpidChecksum, + kpidCharacts, + kpidVa, + kpidId, + kpidShortName, + kpidCreatorApp, + kpidSectorSize, + kpidPosixAttrib, + kpidLink, + kpidError, + + kpidTotalSize = 0x1100, + kpidFreeSpace, + kpidClusterSize, + kpidVolumeName, + + kpidLocalName = 0x1200, + kpidProvider, + + kpidUserDefined = 0x10000 +}; + +#endif diff --git a/SandboxiePlus/MiscHelpers/Archive/7z/CPP/Common/Defs.h b/SandboxiePlus/MiscHelpers/Archive/7z/CPP/Common/Defs.h new file mode 100644 index 00000000..dad3ae8f --- /dev/null +++ b/SandboxiePlus/MiscHelpers/Archive/7z/CPP/Common/Defs.h @@ -0,0 +1,20 @@ +// Common/Defs.h + +#ifndef __COMMON_DEFS_H +#define __COMMON_DEFS_H + +template inline T MyMin(T a, T b) + { return a < b ? a : b; } +template inline T MyMax(T a, T b) + { return a > b ? a : b; } + +template inline int MyCompare(T a, T b) + { return a < b ? -1 : (a == b ? 0 : 1); } + +inline int BoolToInt(bool value) + { return (value ? 1: 0); } + +inline bool IntToBool(int value) + { return (value != 0); } + +#endif diff --git a/SandboxiePlus/MiscHelpers/Archive/7z/CPP/Common/MyCom.h b/SandboxiePlus/MiscHelpers/Archive/7z/CPP/Common/MyCom.h new file mode 100644 index 00000000..2f00c258 --- /dev/null +++ b/SandboxiePlus/MiscHelpers/Archive/7z/CPP/Common/MyCom.h @@ -0,0 +1,225 @@ +// MyCom.h + +#ifndef __MYCOM_H +#define __MYCOM_H + +#include "MyWindows.h" + +#ifndef RINOK +#define RINOK(x) { HRESULT __result_ = (x); if (__result_ != S_OK) return __result_; } +#endif + +template +class CMyComPtr +{ + T* _p; +public: + // typedef T _PtrClass; + CMyComPtr() { _p = NULL;} + CMyComPtr(T* p) {if ((_p = p) != NULL) p->AddRef(); } + CMyComPtr(const CMyComPtr& lp) + { + if ((_p = lp._p) != NULL) + _p->AddRef(); + } + ~CMyComPtr() { if (_p) _p->Release(); } + void Release() { if (_p) { _p->Release(); _p = NULL; } } + operator T*() const { return (T*)_p; } + // T& operator*() const { return *_p; } + T** operator&() { return &_p; } + T* operator->() const { return _p; } + T* operator=(T* p) + { + if (p != 0) + p->AddRef(); + if (_p) + _p->Release(); + _p = p; + return p; + } + T* operator=(const CMyComPtr& lp) { return (*this = lp._p); } + bool operator!() const { return (_p == NULL); } + // bool operator==(T* pT) const { return _p == pT; } + // Compare two objects for equivalence + void Attach(T* p2) + { + Release(); + _p = p2; + } + T* Detach() + { + T* pt = _p; + _p = NULL; + return pt; + } + #ifdef _WIN32 + HRESULT CoCreateInstance(REFCLSID rclsid, REFIID iid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) + { + return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, (void**)&_p); + } + #endif + /* + HRESULT CoCreateInstance(LPCOLESTR szProgID, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) + { + CLSID clsid; + HRESULT hr = CLSIDFromProgID(szProgID, &clsid); + ATLASSERT(_p == NULL); + if (SUCCEEDED(hr)) + hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&_p); + return hr; + } + */ + template + HRESULT QueryInterface(REFGUID iid, Q** pp) const + { + return _p->QueryInterface(iid, (void**)pp); + } +}; + +////////////////////////////////////////////////////////// + +inline HRESULT StringToBstr(LPCOLESTR src, BSTR *bstr) +{ + *bstr = ::SysAllocString(src); + return (*bstr != 0) ? S_OK : E_OUTOFMEMORY; +} + +class CMyComBSTR +{ +public: + BSTR m_str; + CMyComBSTR(): m_str(NULL) {} + CMyComBSTR(LPCOLESTR src) { m_str = ::SysAllocString(src); } + // CMyComBSTR(int nSize) { m_str = ::SysAllocStringLen(NULL, nSize); } + // CMyComBSTR(int nSize, LPCOLESTR sz) { m_str = ::SysAllocStringLen(sz, nSize); } + CMyComBSTR(const CMyComBSTR& src) { m_str = src.MyCopy(); } + /* + CMyComBSTR(REFGUID src) + { + LPOLESTR szGuid; + StringFromCLSID(src, &szGuid); + m_str = ::SysAllocString(szGuid); + CoTaskMemFree(szGuid); + } + */ + ~CMyComBSTR() { ::SysFreeString(m_str); } + CMyComBSTR& operator=(const CMyComBSTR& src) + { + if (m_str != src.m_str) + { + if (m_str) + ::SysFreeString(m_str); + m_str = src.MyCopy(); + } + return *this; + } + CMyComBSTR& operator=(LPCOLESTR src) + { + ::SysFreeString(m_str); + m_str = ::SysAllocString(src); + return *this; + } + unsigned int Length() const { return ::SysStringLen(m_str); } + operator BSTR() const { return m_str; } + BSTR* operator&() { return &m_str; } + BSTR MyCopy() const + { + int byteLen = ::SysStringByteLen(m_str); + BSTR res = ::SysAllocStringByteLen(NULL, byteLen); + memcpy(res, m_str, byteLen); + return res; + } + /* + void Attach(BSTR src) { m_str = src; } + BSTR Detach() + { + BSTR s = m_str; + m_str = NULL; + return s; + } + */ + void Empty() + { + ::SysFreeString(m_str); + m_str = NULL; + } + bool operator!() const { return (m_str == NULL); } +}; + +////////////////////////////////////////////////////////// + +class CMyUnknownImp +{ +public: + ULONG __m_RefCount; + CMyUnknownImp(): __m_RefCount(0) {} +}; + +#define MY_QUERYINTERFACE_BEGIN STDMETHOD(QueryInterface) \ + (REFGUID iid, void **outObject) { + +#define MY_QUERYINTERFACE_ENTRY(i) if (iid == IID_ ## i) \ + { *outObject = (void *)(i *)this; AddRef(); return S_OK; } + +#define MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) if (iid == IID_IUnknown) \ + { *outObject = (void *)(IUnknown *)(i *)this; AddRef(); return S_OK; } + +#define MY_QUERYINTERFACE_BEGIN2(i) MY_QUERYINTERFACE_BEGIN \ + MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \ + MY_QUERYINTERFACE_ENTRY(i) + +#define MY_QUERYINTERFACE_END return E_NOINTERFACE; } + +#define MY_ADDREF_RELEASE \ +STDMETHOD_(ULONG, AddRef)() { return ++__m_RefCount; } \ +STDMETHOD_(ULONG, Release)() { if (--__m_RefCount != 0) \ + return __m_RefCount; delete this; return 0; } + +#define MY_UNKNOWN_IMP_SPEC(i) \ + MY_QUERYINTERFACE_BEGIN \ + i \ + MY_QUERYINTERFACE_END \ + MY_ADDREF_RELEASE + + +#define MY_UNKNOWN_IMP MY_QUERYINTERFACE_BEGIN \ + MY_QUERYINTERFACE_ENTRY_UNKNOWN(IUnknown) \ + MY_QUERYINTERFACE_END \ + MY_ADDREF_RELEASE + +#define MY_UNKNOWN_IMP1(i) MY_UNKNOWN_IMP_SPEC( \ + MY_QUERYINTERFACE_ENTRY_UNKNOWN(i) \ + MY_QUERYINTERFACE_ENTRY(i) \ + ) + +#define MY_UNKNOWN_IMP2(i1, i2) MY_UNKNOWN_IMP_SPEC( \ + MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ + MY_QUERYINTERFACE_ENTRY(i1) \ + MY_QUERYINTERFACE_ENTRY(i2) \ + ) + +#define MY_UNKNOWN_IMP3(i1, i2, i3) MY_UNKNOWN_IMP_SPEC( \ + MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ + MY_QUERYINTERFACE_ENTRY(i1) \ + MY_QUERYINTERFACE_ENTRY(i2) \ + MY_QUERYINTERFACE_ENTRY(i3) \ + ) + +#define MY_UNKNOWN_IMP4(i1, i2, i3, i4) MY_UNKNOWN_IMP_SPEC( \ + MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ + MY_QUERYINTERFACE_ENTRY(i1) \ + MY_QUERYINTERFACE_ENTRY(i2) \ + MY_QUERYINTERFACE_ENTRY(i3) \ + MY_QUERYINTERFACE_ENTRY(i4) \ + ) + +#define MY_UNKNOWN_IMP5(i1, i2, i3, i4, i5) MY_UNKNOWN_IMP_SPEC( \ + MY_QUERYINTERFACE_ENTRY_UNKNOWN(i1) \ + MY_QUERYINTERFACE_ENTRY(i1) \ + MY_QUERYINTERFACE_ENTRY(i2) \ + MY_QUERYINTERFACE_ENTRY(i3) \ + MY_QUERYINTERFACE_ENTRY(i4) \ + MY_QUERYINTERFACE_ENTRY(i5) \ + ) + +#endif diff --git a/SandboxiePlus/MiscHelpers/Archive/7z/CPP/Common/MyInitGuid.h b/SandboxiePlus/MiscHelpers/Archive/7z/CPP/Common/MyInitGuid.h new file mode 100644 index 00000000..d6a48698 --- /dev/null +++ b/SandboxiePlus/MiscHelpers/Archive/7z/CPP/Common/MyInitGuid.h @@ -0,0 +1,22 @@ +// Common/MyInitGuid.h + +#ifndef __COMMON_MY_INITGUID_H +#define __COMMON_MY_INITGUID_H + +#ifdef _WIN32 +#ifdef UNDER_CE +#include +#endif +#include +#ifdef UNDER_CE +DEFINE_GUID(IID_IUnknown, +0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); +#endif +#else +#define INITGUID +#include "MyGuidDef.h" +DEFINE_GUID(IID_IUnknown, +0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); +#endif + +#endif diff --git a/SandboxiePlus/MiscHelpers/Archive/7z/CPP/Common/MyUnknown.h b/SandboxiePlus/MiscHelpers/Archive/7z/CPP/Common/MyUnknown.h new file mode 100644 index 00000000..e9e8666b --- /dev/null +++ b/SandboxiePlus/MiscHelpers/Archive/7z/CPP/Common/MyUnknown.h @@ -0,0 +1,13 @@ +// MyUnknown.h + +#ifndef __MY_UNKNOWN_H +#define __MY_UNKNOWN_H + +#ifdef _WIN32 +#include +#include +#else +#include "MyWindows.h" +#endif + +#endif diff --git a/SandboxiePlus/MiscHelpers/Archive/7z/CPP/Common/MyWindows.cpp b/SandboxiePlus/MiscHelpers/Archive/7z/CPP/Common/MyWindows.cpp new file mode 100644 index 00000000..1283946c --- /dev/null +++ b/SandboxiePlus/MiscHelpers/Archive/7z/CPP/Common/MyWindows.cpp @@ -0,0 +1,109 @@ +// MyWindows.cpp + +#include "StdAfx.h" + +#ifndef _WIN32 + +#include "MyWindows.h" +#include "Types.h" +#include + +static inline void *AllocateForBSTR(size_t cb) { return ::malloc(cb); } +static inline void FreeForBSTR(void *pv) { ::free(pv);} + +static UINT MyStringLen(const wchar_t *s) +{ + UINT i; + for (i = 0; s[i] != '\0'; i++); + return i; +} + +BSTR SysAllocStringByteLen(LPCSTR psz, UINT len) +{ + int realLen = len + sizeof(UINT) + sizeof(OLECHAR) + sizeof(OLECHAR); + void *p = AllocateForBSTR(realLen); + if (p == 0) + return 0; + *(UINT *)p = len; + BSTR bstr = (BSTR)((UINT *)p + 1); + memmove(bstr, psz, len); + Byte *pb = ((Byte *)bstr) + len; + for (int i = 0; i < sizeof(OLECHAR) * 2; i++) + pb[i] = 0; + return bstr; +} + +BSTR SysAllocString(const OLECHAR *sz) +{ + if (sz == 0) + return 0; + UINT strLen = MyStringLen(sz); + UINT len = (strLen + 1) * sizeof(OLECHAR); + void *p = AllocateForBSTR(len + sizeof(UINT)); + if (p == 0) + return 0; + *(UINT *)p = strLen; + BSTR bstr = (BSTR)((UINT *)p + 1); + memmove(bstr, sz, len); + return bstr; +} + +void SysFreeString(BSTR bstr) +{ + if (bstr != 0) + FreeForBSTR((UINT *)bstr - 1); +} + +UINT SysStringByteLen(BSTR bstr) +{ + if (bstr == 0) + return 0; + return *((UINT *)bstr - 1); +} + +UINT SysStringLen(BSTR bstr) +{ + return SysStringByteLen(bstr) / sizeof(OLECHAR); +} + +HRESULT VariantClear(VARIANTARG *prop) +{ + if (prop->vt == VT_BSTR) + SysFreeString(prop->bstrVal); + prop->vt = VT_EMPTY; + return S_OK; +} + +HRESULT VariantCopy(VARIANTARG *dest, VARIANTARG *src) +{ + HRESULT res = ::VariantClear(dest); + if (res != S_OK) + return res; + if (src->vt == VT_BSTR) + { + dest->bstrVal = SysAllocStringByteLen((LPCSTR)src->bstrVal, + SysStringByteLen(src->bstrVal)); + if (dest->bstrVal == 0) + return E_OUTOFMEMORY; + dest->vt = VT_BSTR; + } + else + *dest = *src; + return S_OK; +} + +LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2) +{ + if (ft1->dwHighDateTime < ft2->dwHighDateTime) return -1; + if (ft1->dwHighDateTime > ft2->dwHighDateTime) return 1; + if (ft1->dwLowDateTime < ft2->dwLowDateTime) return -1; + if (ft1->dwLowDateTime > ft2->dwLowDateTime) return 1; + return 0; +} + +DWORD GetLastError() +{ + return 0; +} + +#endif diff --git a/SandboxiePlus/MiscHelpers/Archive/7z/CPP/Common/MyWindows.h b/SandboxiePlus/MiscHelpers/Archive/7z/CPP/Common/MyWindows.h new file mode 100644 index 00000000..8b0e5c06 --- /dev/null +++ b/SandboxiePlus/MiscHelpers/Archive/7z/CPP/Common/MyWindows.h @@ -0,0 +1,204 @@ +// MyWindows.h + +#ifndef __MYWINDOWS_H +#define __MYWINDOWS_H + +#ifdef _WIN32 + +#include + +#else + +#include // for wchar_t +#include + +#include "MyGuidDef.h" + +typedef char CHAR; +typedef unsigned char UCHAR; + +#undef BYTE +typedef unsigned char BYTE; + +typedef short SHORT; +typedef unsigned short USHORT; + +#undef WORD +typedef unsigned short WORD; +typedef short VARIANT_BOOL; + +typedef int INT; +typedef Int32 INT32; +typedef unsigned int UINT; +typedef UInt32 UINT32; +typedef INT32 LONG; // LONG, ULONG and DWORD must be 32-bit +typedef UINT32 ULONG; + +#undef DWORD +typedef UINT32 DWORD; + +typedef Int64 LONGLONG; +typedef UInt64 ULONGLONG; + +typedef struct LARGE_INTEGER { LONGLONG QuadPart; }LARGE_INTEGER; +typedef struct _ULARGE_INTEGER { ULONGLONG QuadPart;} ULARGE_INTEGER; + +typedef const CHAR *LPCSTR; +typedef CHAR TCHAR; +typedef const TCHAR *LPCTSTR; +typedef wchar_t WCHAR; +typedef WCHAR OLECHAR; +typedef const WCHAR *LPCWSTR; +typedef OLECHAR *BSTR; +typedef const OLECHAR *LPCOLESTR; +typedef OLECHAR *LPOLESTR; + +typedef struct _FILETIME +{ + DWORD dwLowDateTime; + DWORD dwHighDateTime; +}FILETIME; + +#define HRESULT LONG +#define FAILED(Status) ((HRESULT)(Status)<0) +typedef ULONG PROPID; +typedef LONG SCODE; + +#define S_OK ((HRESULT)0x00000000L) +#define S_FALSE ((HRESULT)0x00000001L) +#define E_NOTIMPL ((HRESULT)0x80004001L) +#define E_NOINTERFACE ((HRESULT)0x80004002L) +#define E_ABORT ((HRESULT)0x80004004L) +#define E_FAIL ((HRESULT)0x80004005L) +#define STG_E_INVALIDFUNCTION ((HRESULT)0x80030001L) +#define E_OUTOFMEMORY ((HRESULT)0x8007000EL) +#define E_INVALIDARG ((HRESULT)0x80070057L) + +#ifdef _MSC_VER +#define STDMETHODCALLTYPE __stdcall +#else +#define STDMETHODCALLTYPE +#endif + +#define STDMETHOD_(t, f) virtual t STDMETHODCALLTYPE f +#define STDMETHOD(f) STDMETHOD_(HRESULT, f) +#define STDMETHODIMP_(type) type STDMETHODCALLTYPE +#define STDMETHODIMP STDMETHODIMP_(HRESULT) + +#define PURE = 0 + +#define MIDL_INTERFACE(x) struct + +#ifdef __cplusplus + +DEFINE_GUID(IID_IUnknown, +0x00000000, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); +struct IUnknown +{ + STDMETHOD(QueryInterface) (REFIID iid, void **outObject) PURE; + STDMETHOD_(ULONG, AddRef)() PURE; + STDMETHOD_(ULONG, Release)() PURE; + #ifndef _WIN32 + virtual ~IUnknown() {} + #endif +}; + +typedef IUnknown *LPUNKNOWN; + +#endif + +#define VARIANT_TRUE ((VARIANT_BOOL)-1) +#define VARIANT_FALSE ((VARIANT_BOOL)0) + +enum VARENUM +{ + VT_EMPTY = 0, + VT_NULL = 1, + VT_I2 = 2, + VT_I4 = 3, + VT_R4 = 4, + VT_R8 = 5, + VT_CY = 6, + VT_DATE = 7, + VT_BSTR = 8, + VT_DISPATCH = 9, + VT_ERROR = 10, + VT_BOOL = 11, + VT_VARIANT = 12, + VT_UNKNOWN = 13, + VT_DECIMAL = 14, + VT_I1 = 16, + VT_UI1 = 17, + VT_UI2 = 18, + VT_UI4 = 19, + VT_I8 = 20, + VT_UI8 = 21, + VT_INT = 22, + VT_UINT = 23, + VT_VOID = 24, + VT_HRESULT = 25, + VT_FILETIME = 64 +}; + +typedef unsigned short VARTYPE; +typedef WORD PROPVAR_PAD1; +typedef WORD PROPVAR_PAD2; +typedef WORD PROPVAR_PAD3; + +#ifdef __cplusplus + +typedef struct tagPROPVARIANT +{ + VARTYPE vt; + PROPVAR_PAD1 wReserved1; + PROPVAR_PAD2 wReserved2; + PROPVAR_PAD3 wReserved3; + union + { + CHAR cVal; + UCHAR bVal; + SHORT iVal; + USHORT uiVal; + LONG lVal; + ULONG ulVal; + INT intVal; + UINT uintVal; + LARGE_INTEGER hVal; + ULARGE_INTEGER uhVal; + VARIANT_BOOL boolVal; + SCODE scode; + FILETIME filetime; + BSTR bstrVal; + }; +} PROPVARIANT; + +typedef PROPVARIANT tagVARIANT; +typedef tagVARIANT VARIANT; +typedef VARIANT VARIANTARG; + +MY_EXTERN_C HRESULT VariantClear(VARIANTARG *prop); +MY_EXTERN_C HRESULT VariantCopy(VARIANTARG *dest, VARIANTARG *src); + +#endif + +MY_EXTERN_C BSTR SysAllocStringByteLen(LPCSTR psz, UINT len); +MY_EXTERN_C BSTR SysAllocString(const OLECHAR *sz); +MY_EXTERN_C void SysFreeString(BSTR bstr); +MY_EXTERN_C UINT SysStringByteLen(BSTR bstr); +MY_EXTERN_C UINT SysStringLen(BSTR bstr); + +MY_EXTERN_C DWORD GetLastError(); +MY_EXTERN_C LONG CompareFileTime(const FILETIME* ft1, const FILETIME* ft2); + +#define CP_ACP 0 +#define CP_OEMCP 1 + +typedef enum tagSTREAM_SEEK +{ + STREAM_SEEK_SET = 0, + STREAM_SEEK_CUR = 1, + STREAM_SEEK_END = 2 +} STREAM_SEEK; + +#endif +#endif diff --git a/SandboxiePlus/MiscHelpers/Archive/7z/CPP/Common/NewHandler.cpp b/SandboxiePlus/MiscHelpers/Archive/7z/CPP/Common/NewHandler.cpp new file mode 100644 index 00000000..aad6e7d1 --- /dev/null +++ b/SandboxiePlus/MiscHelpers/Archive/7z/CPP/Common/NewHandler.cpp @@ -0,0 +1,116 @@ +// NewHandler.cpp + +#include "StdAfx.h" + +#include + +#include "NewHandler.h" + +// #define DEBUG_MEMORY_LEAK + +#ifndef DEBUG_MEMORY_LEAK + +#ifdef _WIN32 +void * +#ifdef _MSC_VER +__cdecl +#endif +operator new(size_t size) +{ + // void *p = ::HeapAlloc(::GetProcessHeap(), 0, size); + void *p = ::malloc(size); + if (p == 0) + throw CNewException(); + return p; +} + +void +#ifdef _MSC_VER +__cdecl +#endif +operator delete(void *p) throw() +{ + /* + if (p == 0) + return; + ::HeapFree(::GetProcessHeap(), 0, p); + */ + ::free(p); +} +#endif + +#else + +#pragma init_seg(lib) +const int kDebugSize = 1000000; +static void *a[kDebugSize]; +static int index = 0; + +static int numAllocs = 0; +void * __cdecl operator new(size_t size) +{ + numAllocs++; + void *p = HeapAlloc(GetProcessHeap(), 0, size); + if (index == 40) + { + int t = 1; + } + if (index < kDebugSize) + { + a[index] = p; + index++; + } + if (p == 0) + throw CNewException(); + printf("Alloc %6d, size = %8d\n", numAllocs, size); + return p; +} + +class CC +{ +public: + CC() + { + for (int i = 0; i < kDebugSize; i++) + a[i] = 0; + } + ~CC() + { + for (int i = 0; i < kDebugSize; i++) + if (a[i] != 0) + return; + } +} g_CC; + + +void __cdecl operator delete(void *p) +{ + if (p == 0) + return; + /* + for (int i = 0; i < index; i++) + if (a[i] == p) + a[i] = 0; + */ + HeapFree(GetProcessHeap(), 0, p); + numAllocs--; + printf("Free %d\n", numAllocs); +} + +#endif + +/* +int MemErrorVC(size_t) +{ + throw CNewException(); + // return 1; +} +CNewHandlerSetter::CNewHandlerSetter() +{ + // MemErrorOldVCFunction = _set_new_handler(MemErrorVC); +} +CNewHandlerSetter::~CNewHandlerSetter() +{ + // _set_new_handler(MemErrorOldVCFunction); +} +*/ diff --git a/SandboxiePlus/MiscHelpers/Archive/7z/CPP/Common/NewHandler.h b/SandboxiePlus/MiscHelpers/Archive/7z/CPP/Common/NewHandler.h new file mode 100644 index 00000000..215ba05f --- /dev/null +++ b/SandboxiePlus/MiscHelpers/Archive/7z/CPP/Common/NewHandler.h @@ -0,0 +1,16 @@ +// Common/NewHandler.h + +#ifndef __COMMON_NEWHANDLER_H +#define __COMMON_NEWHANDLER_H + +class CNewException {}; + +#ifdef _WIN32 +void +#ifdef _MSC_VER +__cdecl +#endif +operator delete(void *p) throw(); +#endif + +#endif diff --git a/SandboxiePlus/MiscHelpers/Archive/7z/CPP/Common/Types.h b/SandboxiePlus/MiscHelpers/Archive/7z/CPP/Common/Types.h new file mode 100644 index 00000000..9365b327 --- /dev/null +++ b/SandboxiePlus/MiscHelpers/Archive/7z/CPP/Common/Types.h @@ -0,0 +1,11 @@ +// Common/Types.h + +#ifndef __COMMON_TYPES_H +#define __COMMON_TYPES_H + +#include "../../C/Types.h" + +typedef int HRes; + +#endif + diff --git a/SandboxiePlus/MiscHelpers/Archive/7z/CPP/Windows/Defs.h b/SandboxiePlus/MiscHelpers/Archive/7z/CPP/Windows/Defs.h new file mode 100644 index 00000000..281c40c3 --- /dev/null +++ b/SandboxiePlus/MiscHelpers/Archive/7z/CPP/Windows/Defs.h @@ -0,0 +1,17 @@ +// Windows/Defs.h + +#ifndef __WINDOWS_DEFS_H +#define __WINDOWS_DEFS_H + +#include "../Common/MyWindows.h" + +#ifdef _WIN32 +inline bool LRESULTToBool(LRESULT v) { return (v != FALSE); } +inline bool BOOLToBool(BOOL v) { return (v != FALSE); } +inline BOOL BoolToBOOL(bool v) { return (v ? TRUE: FALSE); } +#endif + +inline VARIANT_BOOL BoolToVARIANT_BOOL(bool v) { return (v ? VARIANT_TRUE: VARIANT_FALSE); } +inline bool VARIANT_BOOLToBool(VARIANT_BOOL v) { return (v != VARIANT_FALSE); } + +#endif diff --git a/SandboxiePlus/MiscHelpers/Archive/7z/CPP/Windows/PropVariant.cpp b/SandboxiePlus/MiscHelpers/Archive/7z/CPP/Windows/PropVariant.cpp new file mode 100644 index 00000000..90212e08 --- /dev/null +++ b/SandboxiePlus/MiscHelpers/Archive/7z/CPP/Windows/PropVariant.cpp @@ -0,0 +1,243 @@ +// Windows/PropVariant.cpp + +#include "StdAfx.h" + +#include "PropVariant.h" + +#include "../Common/Defs.h" + +namespace NWindows { +namespace NCOM { + +CPropVariant::CPropVariant(const PROPVARIANT &varSrc) +{ + vt = VT_EMPTY; + InternalCopy(&varSrc); +} + +CPropVariant::CPropVariant(const CPropVariant &varSrc) +{ + vt = VT_EMPTY; + InternalCopy(&varSrc); +} + +CPropVariant::CPropVariant(BSTR bstrSrc) +{ + vt = VT_EMPTY; + *this = bstrSrc; +} + +CPropVariant::CPropVariant(LPCOLESTR lpszSrc) +{ + vt = VT_EMPTY; + *this = lpszSrc; +} + +CPropVariant& CPropVariant::operator=(const CPropVariant &varSrc) +{ + InternalCopy(&varSrc); + return *this; +} +CPropVariant& CPropVariant::operator=(const PROPVARIANT &varSrc) +{ + InternalCopy(&varSrc); + return *this; +} + +CPropVariant& CPropVariant::operator=(BSTR bstrSrc) +{ + *this = (LPCOLESTR)bstrSrc; + return *this; +} + +static const char *kMemException = "out of memory"; + +CPropVariant& CPropVariant::operator=(LPCOLESTR lpszSrc) +{ + InternalClear(); + vt = VT_BSTR; + wReserved1 = 0; + bstrVal = ::SysAllocString(lpszSrc); + if (bstrVal == NULL && lpszSrc != NULL) + { + throw kMemException; + // vt = VT_ERROR; + // scode = E_OUTOFMEMORY; + } + return *this; +} + + +CPropVariant& CPropVariant::operator=(const char *s) +{ + InternalClear(); + vt = VT_BSTR; + wReserved1 = 0; + UINT len = (UINT)strlen(s); + bstrVal = ::SysAllocStringByteLen(0, (UINT)len * sizeof(OLECHAR)); + if (bstrVal == NULL) + { + throw kMemException; + // vt = VT_ERROR; + // scode = E_OUTOFMEMORY; + } + else + { + for (UINT i = 0; i <= len; i++) + bstrVal[i] = s[i]; + } + return *this; +} + +CPropVariant& CPropVariant::operator=(bool bSrc) +{ + if (vt != VT_BOOL) + { + InternalClear(); + vt = VT_BOOL; + } + boolVal = bSrc ? VARIANT_TRUE : VARIANT_FALSE; + return *this; +} + +#define SET_PROP_FUNC(type, id, dest) \ + CPropVariant& CPropVariant::operator=(type value) \ + { if (vt != id) { InternalClear(); vt = id; } \ + dest = value; return *this; } + +SET_PROP_FUNC(Byte, VT_UI1, bVal) +SET_PROP_FUNC(Int16, VT_I2, iVal) +SET_PROP_FUNC(Int32, VT_I4, lVal) +SET_PROP_FUNC(UInt32, VT_UI4, ulVal) +SET_PROP_FUNC(UInt64, VT_UI8, uhVal.QuadPart) +SET_PROP_FUNC(const FILETIME &, VT_FILETIME, filetime) + +static HRESULT MyPropVariantClear(PROPVARIANT *prop) +{ + switch(prop->vt) + { + case VT_UI1: + case VT_I1: + case VT_I2: + case VT_UI2: + case VT_BOOL: + case VT_I4: + case VT_UI4: + case VT_R4: + case VT_INT: + case VT_UINT: + case VT_ERROR: + case VT_FILETIME: + case VT_UI8: + case VT_R8: + case VT_CY: + case VT_DATE: + prop->vt = VT_EMPTY; + prop->wReserved1 = 0; + return S_OK; + } + return ::VariantClear((VARIANTARG *)prop); +} + +HRESULT CPropVariant::Clear() +{ + return MyPropVariantClear(this); +} + +HRESULT CPropVariant::Copy(const PROPVARIANT* pSrc) +{ + ::VariantClear((tagVARIANT *)this); + switch(pSrc->vt) + { + case VT_UI1: + case VT_I1: + case VT_I2: + case VT_UI2: + case VT_BOOL: + case VT_I4: + case VT_UI4: + case VT_R4: + case VT_INT: + case VT_UINT: + case VT_ERROR: + case VT_FILETIME: + case VT_UI8: + case VT_R8: + case VT_CY: + case VT_DATE: + memmove((PROPVARIANT*)this, pSrc, sizeof(PROPVARIANT)); + return S_OK; + } + return ::VariantCopy((tagVARIANT *)this, (tagVARIANT *)const_cast(pSrc)); +} + + +HRESULT CPropVariant::Attach(PROPVARIANT *pSrc) +{ + HRESULT hr = Clear(); + if (FAILED(hr)) + return hr; + memcpy(this, pSrc, sizeof(PROPVARIANT)); + pSrc->vt = VT_EMPTY; + return S_OK; +} + +HRESULT CPropVariant::Detach(PROPVARIANT *pDest) +{ + HRESULT hr = MyPropVariantClear(pDest); + if (FAILED(hr)) + return hr; + memcpy(pDest, this, sizeof(PROPVARIANT)); + vt = VT_EMPTY; + return S_OK; +} + +HRESULT CPropVariant::InternalClear() +{ + HRESULT hr = Clear(); + if (FAILED(hr)) + { + vt = VT_ERROR; + scode = hr; + } + return hr; +} + +void CPropVariant::InternalCopy(const PROPVARIANT *pSrc) +{ + HRESULT hr = Copy(pSrc); + if (FAILED(hr)) + { + if (hr == E_OUTOFMEMORY) + throw kMemException; + vt = VT_ERROR; + scode = hr; + } +} + +int CPropVariant::Compare(const CPropVariant &a) +{ + if (vt != a.vt) + return MyCompare(vt, a.vt); + switch (vt) + { + case VT_EMPTY: return 0; + // case VT_I1: return MyCompare(cVal, a.cVal); + case VT_UI1: return MyCompare(bVal, a.bVal); + case VT_I2: return MyCompare(iVal, a.iVal); + case VT_UI2: return MyCompare(uiVal, a.uiVal); + case VT_I4: return MyCompare(lVal, a.lVal); + case VT_UI4: return MyCompare(ulVal, a.ulVal); + // case VT_UINT: return MyCompare(uintVal, a.uintVal); + case VT_I8: return MyCompare(hVal.QuadPart, a.hVal.QuadPart); + case VT_UI8: return MyCompare(uhVal.QuadPart, a.uhVal.QuadPart); + case VT_BOOL: return -MyCompare(boolVal, a.boolVal); + case VT_FILETIME: return ::CompareFileTime(&filetime, &a.filetime); + case VT_BSTR: + return 0; // Not implemented + // return MyCompare(aPropVarint.cVal); + default: return 0; + } +} + +}} diff --git a/SandboxiePlus/MiscHelpers/Archive/7z/CPP/Windows/PropVariant.h b/SandboxiePlus/MiscHelpers/Archive/7z/CPP/Windows/PropVariant.h new file mode 100644 index 00000000..d018034e --- /dev/null +++ b/SandboxiePlus/MiscHelpers/Archive/7z/CPP/Windows/PropVariant.h @@ -0,0 +1,56 @@ +// Windows/PropVariant.h + +#ifndef __WINDOWS_PROPVARIANT_H +#define __WINDOWS_PROPVARIANT_H + +#include "../Common/MyWindows.h" +#include "../Common/Types.h" + +namespace NWindows { +namespace NCOM { + +class CPropVariant : public tagPROPVARIANT +{ +public: + CPropVariant() { vt = VT_EMPTY; wReserved1 = 0; } + ~CPropVariant() { Clear(); } + CPropVariant(const PROPVARIANT &varSrc); + CPropVariant(const CPropVariant &varSrc); + CPropVariant(BSTR bstrSrc); + CPropVariant(LPCOLESTR lpszSrc); + CPropVariant(bool bSrc) { vt = VT_BOOL; wReserved1 = 0; boolVal = (bSrc ? VARIANT_TRUE : VARIANT_FALSE); }; + CPropVariant(Byte value) { vt = VT_UI1; wReserved1 = 0; bVal = value; } + CPropVariant(Int16 value) { vt = VT_I2; wReserved1 = 0; iVal = value; } + CPropVariant(Int32 value) { vt = VT_I4; wReserved1 = 0; lVal = value; } + CPropVariant(UInt32 value) { vt = VT_UI4; wReserved1 = 0; ulVal = value; } + CPropVariant(UInt64 value) { vt = VT_UI8; wReserved1 = 0; uhVal.QuadPart = value; } + CPropVariant(const FILETIME &value) { vt = VT_FILETIME; wReserved1 = 0; filetime = value; } + + CPropVariant& operator=(const CPropVariant &varSrc); + CPropVariant& operator=(const PROPVARIANT &varSrc); + CPropVariant& operator=(BSTR bstrSrc); + CPropVariant& operator=(LPCOLESTR lpszSrc); + CPropVariant& operator=(const char *s); + CPropVariant& operator=(bool bSrc); + CPropVariant& operator=(Byte value); + CPropVariant& operator=(Int16 value); + CPropVariant& operator=(Int32 value); + CPropVariant& operator=(UInt32 value); + CPropVariant& operator=(Int64 value); + CPropVariant& operator=(UInt64 value); + CPropVariant& operator=(const FILETIME &value); + + HRESULT Clear(); + HRESULT Copy(const PROPVARIANT *pSrc); + HRESULT Attach(PROPVARIANT *pSrc); + HRESULT Detach(PROPVARIANT *pDest); + + HRESULT InternalClear(); + void InternalCopy(const PROPVARIANT *pSrc); + + int Compare(const CPropVariant &a1); +}; + +}} + +#endif diff --git a/SandboxiePlus/MiscHelpers/Archive/7z/CPP/Windows/StdAfx.h b/SandboxiePlus/MiscHelpers/Archive/7z/CPP/Windows/StdAfx.h new file mode 100644 index 00000000..8b383c5b --- /dev/null +++ b/SandboxiePlus/MiscHelpers/Archive/7z/CPP/Windows/StdAfx.h @@ -0,0 +1,9 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../Common/MyWindows.h" +#include "../Common/NewHandler.h" + +#endif diff --git a/SandboxiePlus/MiscHelpers/Archive/Archive.cpp b/SandboxiePlus/MiscHelpers/Archive/Archive.cpp new file mode 100644 index 00000000..b4c3eca4 --- /dev/null +++ b/SandboxiePlus/MiscHelpers/Archive/Archive.cpp @@ -0,0 +1,503 @@ +#include "stdafx.h" +#include "ArchiveHelper.h" +#include "Archive.h" +#include "ArchiveInterface.h" +#include "ArchiveOpener.h" +#include "ArchiveExtractor.h" +#include "ArchiveUpdater.h" + +#include "SplitFile.h" + +#ifdef USE_7Z + +CArchiveInterface theArc; + +struct CArchive::SArchive +{ + SArchive(CMyComPtr &InArchive) {In = InArchive;} + ~SArchive() {In->Close();} + CMyComPtr In; +}; + +CArchive::CArchive(const QString &ArchivePath, QIODevice* pDevice) +{ + Init(); + + m_pDevice = pDevice; + m_ArchivePath = ArchivePath; + m_Archive = NULL; + m_PartSize = -1; + m_PasswordUsed = false; +} + +void CArchive::Init() +{ + if(!theArc.IsOperational()) + theArc.Init(); +} + +bool CArchive::IsInit() +{ + return theArc.IsOperational(); +} + +CArchive::~CArchive() +{ + Close(); +} + +int CArchive::Open() +{ + if(!theArc.IsOperational()) + { + LogError("Couldnt open interface"); + return 0; // failed + } + + if(m_Archive) + { + LogError("archive is already open"); + return 0; // failes + } + + if(!m_pDevice && !QFile::exists(m_ArchivePath)) + { + LogError("archive does not exist"); + return 0; // failed + } + + SArcInfo Info = GetArcInfo(m_ArchivePath); + if(Info.FormatIndex == 0) + return -1; // unsupported format + + for (int i = 0; i <= theArc.GetFormatCount(); i++) + { + CMyComPtr InArchive; + if(!theArc.CreateInArchive(i ? i : Info.FormatIndex, InArchive)) // First try the most likely one and than try everyone else + break; + if (!InArchive) + continue; + + // Open Archive + const UInt64 kMaxCheckStartPosition = 1 << 22; // 4MB + CMyComPtr callback(new CArchiveOpener(this)); + HRESULT Ret = InArchive->Open(new CArchiveIO(m_pDevice ? m_pDevice : new QFile(m_ArchivePath), QIODevice::ReadOnly, m_pDevice == NULL), &kMaxCheckStartPosition, callback); + if(Ret != S_OK) + { + InArchive->Close(); + if(Ret == S_FALSE) + continue; // not supported + if(Ret == E_ABORT) + LogError(QString("Password required for archive")); + break; // error + } + + //TRACE(L"%S Archive %S Opened for extraction", QS2CS(theArc.GetArchiveName(i ? i : Info.FormatIndex)), QS2CS(m_ArchivePath)); + m_Archive = new SArchive(InArchive); + break; + } + + if(m_Archive == NULL) + { + LogError("Failed to open archive"); + return 0; // failed + } + + // list archive content + UInt32 numItems = 0; + m_Archive->In->GetNumberOfItems(&numItems); + for (UInt32 i = 0; i < numItems; i++) + { + NWindows::NCOM::CPropVariant prop; + SFile File(i); + UInt32 numProps = 0; + m_Archive->In->GetNumberOfProperties(&numProps); + for(UInt32 j=0; j < numProps; j++) + { + m_Archive->In->GetProperty(i, j, &prop); + + QVariant Propertie; + switch (prop.vt) + { + case VT_BSTR: Propertie = QString::fromStdWString(prop.bstrVal); break; + case VT_UI1: Propertie = prop.bVal; break; + case VT_UI2: Propertie = prop.uiVal; break; + case VT_UI4: Propertie = (qint32)prop.ulVal; break; + case VT_UI8: Propertie = (qint64)prop.uhVal.QuadPart; break; + case VT_BOOL: Propertie = VARIANT_BOOLToBool(prop.boolVal); break; + case VT_FILETIME: Propertie = *reinterpret_cast(&prop.filetime); break; // ToDo + default: + //TRACE(L"Unhandled archive property %S (%d)", QS2CS(GetPropertyName(j)), prop.vt); + case VT_EMPTY: + continue; + } + + File.Properties.insert(GetPropertyName(j), Propertie); + //TRACE(L" >> File %S: %S=%S", QS2CS(File.Properties["Path"].toString()), QS2CS(GetPropertyName(j)), QS2CS(Propertie.toString())); + } + m_Files.append(File); + } + + return 1; // success +} + +bool CArchive::Extract(QString Path) +{ + if(!m_Archive) + { + LogError("archive is not open"); + return false; + } + + if(Path.isEmpty()) + Path = m_ArchivePath.left(m_ArchivePath.lastIndexOf(".")) + "/"; + else if(Path.right(1) != "/") + Path.append("/"); + + QMap Files; + foreach(const SFile& File, m_Files) + { + if(File.Properties["IsDir"].toBool()) + continue; + + Files.insert(File.ArcIndex, new QFile(PrepareExtraction(File.Properties["Path"].toString(), Path))); + } + + return Extract(&Files); +} + +bool CArchive::Extract(QMap *FileList, bool bDelete) +{ + if(!m_Archive) + { + LogError("archive is not open"); + return false; + } + + QMap Files; + foreach(int ArcIndex, FileList->keys()) + { + FileProperty(ArcIndex, "Error", QVariant()); + Files.insert(ArcIndex, new CArchiveIO(FileList->value(ArcIndex), QIODevice::NotOpen, bDelete)); + } + + CMyComPtr callback(new CArchiveExtractor(this, Files)); + if(m_Archive->In->Extract(NULL, (UInt32)(Int32)(-1), false, callback) != S_OK) + { + LogError(QString("Error(s) While extracting from archive")); + return false; + } + + foreach(int ArcIndex, FileList->keys()) + { + QVariant Error = FileProperty(ArcIndex, "Error"); + if(Error.isValid()) + return false; + } + return true; +} + +bool CArchive::Close() +{ + m_Files.clear(); + if(m_Archive) + { + delete m_Archive; + m_Archive = NULL; + return true; + } + return false; +} + +bool CArchive::Update(QMap *FileList, bool bDelete, int Level) +{ + if(!theArc.IsOperational()) + { + LogError("Couldnt open interface"); + return false; + } + + SArcInfo Info = GetArcInfo(m_ArchivePath); + + CMyComPtr OutArchive; + if(!theArc.CreateOutArchive(Info.FormatIndex, OutArchive) || !OutArchive) + { + LogError("Archive can not be updated"); + return false; + } + + CMyComPtr setProperties; + OutArchive->QueryInterface(IID_ISetProperties, (void **)&setProperties); + if (!setProperties) + { + TRACE(L"ISetProperties unsupported"); + Q_ASSERT(0); + } + else + { + /* http://www.dotnetperls.com/7-zip-examples + Switch -mx0: Don't compress at all. This is called "copy mode." + Switch -mx1: Low compression. This is called "fastest" mode. + Switch -mx3: Fast compression mode. Will set various parameters automatically. + Switch -mx5: Same as above, but "normal." + Switch -mx7: This means "maximum" compression. + Switch -mx9: This means "ultra" compression. You probably want to use this. + + Switch -ms=on: Enable solid mode. This is the default so you won't often need this. + Switch -ms=off: Disable solid mode. This is useful when you need to update individual files. Will reduce compression ratios normally. + */ + const wchar_t *names[] = + { + L"s", + L"x", + L"he" + }; + const int kNumProps = sizeof(names) / sizeof(names[0]); + NWindows::NCOM::CPropVariant values[kNumProps] = + { + false, // solid mode OFF + (UInt32)Level, // compression level = 9 - ultra + true // file name encryption (7z only) + }; + + if(setProperties->SetProperties(names, values, kNumProps) != S_OK) + { + TRACE(L"ISetProperties failed"); + Q_ASSERT(0); + } + } + + QMap Files; + foreach(int ArcIndex, FileList->keys()) + { + Files.insert(ArcIndex, new CArchiveIO(FileList->value(ArcIndex), QIODevice::NotOpen, bDelete)); + FileProperty(ArcIndex, "Size", FileList->value(ArcIndex)->size()); + FileProperty(ArcIndex, "Attrib", 32); + } + + //TRACE(L"%S Archive %S Opened for update", QS2CS(theArc.GetArchiveName(Info.FormatIndex)), QS2CS(m_ArchivePath)); + + QIODevice* pFile = NULL; + bool bUpdate = false; + if(!m_pDevice) + { + if(m_PartSize != -1) + { + if(m_Archive) + { + LogError("can not update multipart archive"); + return false; + } + pFile = new CSplitFile(m_ArchivePath, m_PartSize); + } + else if(m_Archive) + { + bUpdate = true; + pFile = new QFile(m_ArchivePath + ".tmp"); + } + else + pFile = new QFile(m_ArchivePath); + } + else if(m_pDevice->isOpen()) + { + bUpdate = true; + m_pDevice->close(); + } + + CMyComPtr callback(new CArchiveUpdater(this, Files)); + if(OutArchive->UpdateItems(new CArchiveIO(m_pDevice ? m_pDevice : pFile, QIODevice::WriteOnly, m_pDevice == NULL), FileCount(), callback) != S_OK) + { + LogError("Error(s) while updateing Archive"); + return false; + } + + Close(); // close even if it wasnt open to clear the file list + if(bUpdate) + { + if(!m_pDevice) + { + QFile::remove(m_ArchivePath); + QFile::rename(m_ArchivePath + ".tmp", m_ArchivePath); + } + return Open(); + } + return true; +} + +int CArchive::AddFile(QString Path) +{ + if(FindByPath(Path) != -1) + return -1; + + SFile File(m_Files.isEmpty() ? 0 : m_Files.last().ArcIndex+1); + //File.NewData = true; + m_Files.append(File); + FileProperty(File.ArcIndex,"Path",Path); + return File.ArcIndex; +} + +int CArchive::FindByPath(QString Path) +{ + if(Path.left(1) == "/") + Path.remove(0,1); + foreach(const SFile& File, m_Files) + { + if(Path.compare(File.Properties["Path"].toString().replace("\\","/")) == 0) + return File.ArcIndex; + } + return -1; +} + +int CArchive::FindByIndex(int Index) +{ + if(Index > m_Files.count()) + return -1; + return m_Files[Index].ArcIndex; +} + +int CArchive::GetIndex(int ArcIndex) +{ + for(int Index = 0; Index < m_Files.count(); Index++) + { + const SFile& File = m_Files[Index]; + if(File.ArcIndex == ArcIndex) + return Index; + } + return -1; +} + +void CArchive::RemoveFile(int ArcIndex) +{ + int Index = GetIndex(ArcIndex); + if(Index != -1) + m_Files.remove(Index); +} + +QString CArchive::PrepareExtraction(QString FileName, QString Path) +{ + // Cleanup + FileName.replace("\\","/"); + FileName.remove(QRegularExpression("[:*?<>|\"]")); + if(FileName.left(1) == "/") + FileName.remove(0,1); + + // Create Sub Paths if needed + QString SubPath = Path; + int Pos = FileName.lastIndexOf("/"); + if(Pos != -1) + SubPath += FileName.left(Pos); + if(!QDir().exists(SubPath)) + QDir().mkpath(SubPath); + + return Path + FileName; +} + +QString CArchive::GetNextPart(QString FileName) +{ + if(!m_AuxParts.isEmpty()) + { + SArcInfo ArcInfo = GetArcInfo(FileName); + foreach(const QString& Part, m_AuxParts) + { + if(GetArcInfo(Part).PartNumber == ArcInfo.PartNumber) + { + FileName = Part; + break; + } + } + } + + int Pos = m_ArchivePath.lastIndexOf("/"); + if(Pos != -1) + FileName.prepend(m_ArchivePath.left(Pos+1)); + return FileName; +} + +QVariant CArchive::FileProperty(int ArcIndex, QString Name) +{ + int Index = GetIndex(ArcIndex); + if(Index != -1) + return m_Files[Index].Properties.value(Name); + return QVariant(); +} + +void CArchive::FileProperty(int ArcIndex, QString Name, QVariant Value) +{ + int Index = GetIndex(ArcIndex); + if(Index != -1) + { + m_Files[Index].Properties.insert(Name, Value); + //m_Files[Index].NewInfo = true; + } +} + +#endif + +SArcInfo GetArcInfo(const QString &FileName) +{ + SArcInfo ArcInfo; + ArcInfo.FileName = FileName.trimmed(); + + int Pos = ArcInfo.FileName.lastIndexOf("/"); + if(Pos != -1) + ArcInfo.FileName.remove(0,Pos+1); + + Pos = ArcInfo.FileName.lastIndexOf("."); + if(Pos != -1) + { + ArcInfo.ArchiveExt = ArcInfo.FileName.mid(Pos+1); + ArcInfo.FileName.remove(Pos, ArcInfo.FileName.length()-Pos); + } + + // RAR spetial case + if(ArcInfo.ArchiveExt.indexOf(QRegularExpression("(rar|rev|r[0-9]{2,})", QRegularExpression::CaseInsensitiveOption)) == 0) + { + if(ArcInfo.ArchiveExt.compare("rar", Qt::CaseInsensitive) == 0 || ArcInfo.ArchiveExt.compare("rev", Qt::CaseInsensitive) == 0) // is this a new naming scheme + { + ArcInfo.PartNumber = 1; // rar is always to be threaded like multipart + + Pos = ArcInfo.FileName.lastIndexOf("part", -1, Qt::CaseInsensitive); + if(Pos != -1) + { + int Pos1 = Pos+4; + int Pos2 = ArcInfo.FileName.indexOf(QRegularExpression("[^0-9]"), Pos1); + if(Pos2 == -1) + Pos2 = ArcInfo.FileName.length(); + + ArcInfo.FixRar = (ArcInfo.FileName.lastIndexOf(QRegularExpression("\\.part[0-9]+$", QRegularExpression::CaseInsensitiveOption), -1) + 1 != Pos); + + ArcInfo.PartNumber = ArcInfo.FileName.mid(Pos1, Pos2-Pos1).toInt(); + ArcInfo.FileName.remove(Pos, Pos2-Pos); + } + } + else // no its the old naming scheme + { + Pos = ArcInfo.ArchiveExt.indexOf(QRegularExpression("[0-9]", QRegularExpression::CaseInsensitiveOption)); + ArcInfo.PartNumber = ArcInfo.ArchiveExt.mid(Pos).toInt()+2; // .rar is 1 .r00 is 2, etc.... + } + ArcInfo.ArchiveExt = "rar"; + } + + if(ArcInfo.ArchiveExt.indexOf(QRegularExpression("(part|)[0-9]{3,}")) == 0) + { + ArcInfo.PartNumber = ArcInfo.ArchiveExt.toInt(); + ArcInfo.ArchiveExt.clear(); + + Pos = ArcInfo.FileName.lastIndexOf("."); + if(Pos != -1) + { + ArcInfo.ArchiveExt = ArcInfo.FileName.mid(Pos+1); + ArcInfo.FileName.remove(Pos, ArcInfo.FileName.length()-Pos); + } + } + +#ifdef USE_7Z + if(ArcInfo.ArchiveExt.indexOf(QRegularExpression("(rar|zip|7z)", QRegularExpression::CaseInsensitiveOption)) != -1) + ArcInfo.FormatIndex = theArc.FindByExt(ArcInfo.ArchiveExt); +#endif + + ArcInfo.FileName += "." + ArcInfo.ArchiveExt; + if(ArcInfo.FormatIndex == 0) // not a known archive + ArcInfo.ArchiveExt.clear(); + return ArcInfo; +} \ No newline at end of file diff --git a/SandboxiePlus/MiscHelpers/Archive/Archive.h b/SandboxiePlus/MiscHelpers/Archive/Archive.h new file mode 100644 index 00000000..08f18a8c --- /dev/null +++ b/SandboxiePlus/MiscHelpers/Archive/Archive.h @@ -0,0 +1,124 @@ +#pragma once + +#include "../mischelpers_global.h" + +// *Note* no archiver specific includes here + +#define USE_7Z + +#ifdef USE_7Z + +class MISCHELPERS_EXPORT CArchive +{ +public: + CArchive(const QString &ArchivePath, QIODevice* pDevice = NULL); + static void Init(); + static bool IsInit(); + ~CArchive(); + + QString GetPassword(bool bSet = false) {if(bSet) m_PasswordUsed = true; return m_Password;} + void SetPassword(const QString& Password) {m_Password = Password; m_PasswordUsed = false;} + bool HasUsedPassword() {return m_PasswordUsed;} + bool SetPartSize(quint64 PartSize) {if(m_Archive) return false; m_PartSize = PartSize; return true;} + + int Open(); + bool Extract(QString Path = ""); + bool Extract(QMap *FileList, bool bDelete = true); + bool Close(); + + bool Update(QMap *FileList, bool bDelete = true, int Level = 0); + + int AddFile(QString Path); + int FileCount() {return m_Files.count();} + int FindByPath(QString Path); + int FindByIndex(int Index); + void RemoveFile(int ArcIndex); + + QVariant FileProperty(int ArcIndex, QString Name); + void FileProperty(int ArcIndex, QString Name, QVariant Value); + + quint64 GetPartSize() {return m_PartSize;} + const QString& GetArchivePath() {return m_ArchivePath;} + double GetProgress() {return m_Progress.GetValue();} + + void SetPartList(const QStringList& Parts) {m_AuxParts = Parts;} + + static QString PrepareExtraction(QString FileName, QString Path); + +protected: + int GetIndex(int ArcIndex); + + QString GetNextPart(QString FileName); + + virtual void LogError(const QString &Error) {} + + friend class CArchiveOpener; + friend class CArchiveExtractor; + friend class CArchiveUpdater; + + QString m_ArchivePath; + QIODevice* m_pDevice; + QString m_Password; + bool m_PasswordUsed; + quint64 m_PartSize; + + QStringList m_AuxParts; + + struct SArchive; + SArchive* m_Archive; + + struct SFile + { + SFile(int Index = -1) + { + ArcIndex = Index; + //NewData = false; + //NewInfo = false; + } + int ArcIndex; + QVariantMap Properties; + //bool NewData; + //bool NewInfo; + }; + QVector m_Files; + + struct SProgress + { + SProgress(){ + uTotal = 0; + uCompleted = 0; + } + void SetTotal(quint64 Total) {uTotal = Total;} + void SetCompleted(quint64 Completed) {uCompleted = Completed;} + double GetValue() + { + double Total = uTotal; + double Completed = uCompleted; + return (Total > 0) ? Completed/Total : 0; + } + quint64 uTotal; + quint64 uCompleted; + } m_Progress; +}; + +#endif + +struct MISCHELPERS_EXPORT SArcInfo +{ + SArcInfo() + { + PartNumber = -1; // Single Part + FormatIndex = 0; // Not an archive (only a split file) or unsupported format + FixRar = false; // indicates if rar file name needs fixing + } + QString FileName; // Filename after extension removal + QString ArchiveExt; // Archive Extension + int FormatIndex; // Archive format Index + int PartNumber; // Part Number, -1 means not a multipart , 1 means first part + bool FixRar; +}; + +SArcInfo MISCHELPERS_EXPORT GetArcInfo(const QString &FileName); + +class CArchiveInterface; +extern CArchiveInterface theArc; diff --git a/SandboxiePlus/MiscHelpers/Archive/ArchiveExtractor.cpp b/SandboxiePlus/MiscHelpers/Archive/ArchiveExtractor.cpp new file mode 100644 index 00000000..cdbb9d6c --- /dev/null +++ b/SandboxiePlus/MiscHelpers/Archive/ArchiveExtractor.cpp @@ -0,0 +1,103 @@ +#include "stdafx.h" +#include "ArchiveExtractor.h" +#include "Archive.h" + +#ifdef USE_7Z + +CArchiveExtractor::CArchiveExtractor(CArchive* pArchive, const QMap& Files) +{ + m_pArchive = pArchive; + m_Index = -1; + m_Files = Files; +} + +CArchiveExtractor::~CArchiveExtractor() +{ + foreach(CArchiveIO* pFile, m_Files) + delete pFile; +} + +STDMETHODIMP CArchiveExtractor::SetTotal(UInt64 size) +{ + m_pArchive->m_Progress.SetTotal(size); + return S_OK; +} + +STDMETHODIMP CArchiveExtractor::SetCompleted(const UInt64 *completeValue) +{ + ASSERT(completeValue); + m_pArchive->m_Progress.SetCompleted(*completeValue); + return S_OK; +} + +STDMETHODIMP CArchiveExtractor::PrepareOperation (Int32 askExtractMode) +{ + switch (askExtractMode) + { + case NArchive::NExtract::NAskMode::kExtract: + //TRACE(L"Extracting ..."); + break; + case NArchive::NExtract::NAskMode::kTest: + //TRACE(L"Testing ..."); + break; + case NArchive::NExtract::NAskMode::kSkip: + //TRACE(L"Skipping ..."); + break; + default: Q_ASSERT(0); + } + return S_OK; +} + +STDMETHODIMP CArchiveExtractor::GetStream (UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode) +{ + *outStream = NULL; + Q_ASSERT(index < m_pArchive->m_Files.count()); + m_Index = index; + //TRACE(L"Archive Item '%S'", QS2CS(m_pArchive->FileProperty(m_Index, "Path").toString())); + if(CArchiveIO* pFile = m_Files.take(m_Index)) + { + Q_ASSERT(askExtractMode == NArchive::NExtract::NAskMode::kExtract); + if (!pFile->Open(QIODevice::WriteOnly)) + return S_FALSE; + CMyComPtr outStreamLoc = pFile; + *outStream = outStreamLoc.Detach(); + } + return S_OK; +} + +STDMETHODIMP CArchiveExtractor::SetOperationResult (Int32 operationResult) +{ + switch(operationResult) + { + case NArchive::NExtract::NOperationResult::kOK: + //TRACE(L"... Completed"); + break; + case NArchive::NExtract::NOperationResult::kUnSupportedMethod: + //TRACE(L"... Error (Un Supported Method)"); + m_pArchive->LogError(QString("File Extraction Failes (Un Supported Method): %1").arg(m_pArchive->FileProperty(m_Index, "Path").toString())); + m_pArchive->FileProperty(m_Index, "Error", "Un Supported Method"); + break; + case NArchive::NExtract::NOperationResult::kCRCError: + //TRACE(L"... Error (CRC)"); + m_pArchive->LogError(QString("File Extraction Failes (CRC Error): %1").arg(m_pArchive->FileProperty(m_Index, "Path").toString())); + m_pArchive->FileProperty(m_Index, "Error", "CRC Error"); + break; + case NArchive::NExtract::NOperationResult::kDataError: + //TRACE(L"... Error (Data)"); + m_pArchive->LogError(QString("File Extraction Failes (Data Error): %1").arg(m_pArchive->FileProperty(m_Index, "Path").toString())); + m_pArchive->FileProperty(m_Index, "Error", "Data Error"); + break; + default: Q_ASSERT(0); + } + return S_OK; +} + +STDMETHODIMP CArchiveExtractor::CryptoGetTextPassword(BSTR *password) +{ + QString Password = m_pArchive->GetPassword(true); + if(Password.isEmpty()) + return E_ABORT; + return StringToBstr(Password.toStdWString().c_str(), password); +} + +#endif \ No newline at end of file diff --git a/SandboxiePlus/MiscHelpers/Archive/ArchiveExtractor.h b/SandboxiePlus/MiscHelpers/Archive/ArchiveExtractor.h new file mode 100644 index 00000000..d088dfaa --- /dev/null +++ b/SandboxiePlus/MiscHelpers/Archive/ArchiveExtractor.h @@ -0,0 +1,34 @@ +#pragma once + +#include "ArchiveHelper.h" + +#ifdef USE_7Z + +class CArchiveExtractor: public IArchiveExtractCallback, public ICryptoGetTextPassword, public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP2(IArchiveExtractCallback, ICryptoGetTextPassword) + + CArchiveExtractor(CArchive* pArchive, const QMap& Files); + ~CArchiveExtractor(); + + // IProgress + STDMETHOD(SetTotal)(UInt64 size); + STDMETHOD(SetCompleted)(const UInt64 *completeValue); + + // IArchiveExtractCallback + STDMETHOD(PrepareOperation)(Int32 askExtractMode); + STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode); + STDMETHOD(SetOperationResult)(Int32 operationResult); + + // ICryptoGetTextPassword + STDMETHOD(CryptoGetTextPassword)(BSTR *password); + +protected: + CArchive* m_pArchive; + + QMap m_Files; + int m_Index; +}; + +#endif \ No newline at end of file diff --git a/SandboxiePlus/MiscHelpers/Archive/ArchiveFS.cpp b/SandboxiePlus/MiscHelpers/Archive/ArchiveFS.cpp new file mode 100644 index 00000000..a152e11e --- /dev/null +++ b/SandboxiePlus/MiscHelpers/Archive/ArchiveFS.cpp @@ -0,0 +1,284 @@ +#include "stdafx.h" +#include "ArchiveFS.h" +#include "../Common/Common.h" + +////////////////////////////////////////////////////////////////////////////////////////// +// C7zFileEngineIterator +// + +class C7zFileEngineIterator : public QAbstractFileEngineIterator +{ +public: + C7zFileEngineIterator(QDir::Filters filters, const QStringList& filterNames, + const QStringList& allEntries) + : QAbstractFileEngineIterator(filters, filterNames), entries(allEntries), index(0) {} + ~C7zFileEngineIterator() {} + + QString next() override + { + if (!hasNext()) + return QString(); + ++index; + return currentFilePath(); + } + bool hasNext() const override + { + return index < entries.size(); + } + + QString currentFileName() const override + { + if (index <= 0 || index > entries.size()) + return QString(); + return entries.at(index - 1); + } + +private: + mutable QStringList entries; + mutable int index; +}; + + +////////////////////////////////////////////////////////////////////////////////////////// +// C7zFileEngine +// + +C7zFileEngine::C7zFileEngine(const QString& filename, CArchive* pArchive, QMutex* pMutex) + : _flags(0), _size(0), _pos(0), _pArchive(pArchive), _pMutex(pMutex) +{ + setFileName(filename); +} + +C7zFileEngine::~C7zFileEngine() +{ + close(); +} + +bool C7zFileEngine::open(QIODevice::OpenMode openMode) +{ + close(); + + //if (openMode & QIODevice::WriteOnly) { + // + //} else + if (openMode & QIODevice::ReadOnly) { + + QMutexLocker Lock(_pMutex); + + QMap Files; + Files.insert(_index, new QBuffer(&_data)); + _pArchive->Extract(&Files); + + _size = _data.size(); + _pos = 0; + + } else + //if (openMode & QIODevice::Append) { + // + //} else + { + qWarning("Bad file open mode: %d", (int)openMode); + return false; + } + + return true; +} + +bool C7zFileEngine::close() +{ + if (!isOpened()) + return false; + + _data.clear(); + _size = 0; + _pos = 0; + + return true; +} + +bool C7zFileEngine::flush() +{ + return true; +} + +qint64 C7zFileEngine::size() const +{ + return _size; +} + +qint64 C7zFileEngine::pos() const +{ + return _pos; +} + +bool C7zFileEngine::seek(qint64 pos) +{ + _pos = pos; + return true; +} + +bool C7zFileEngine::isSequential() const +{ + return true; +} + +bool C7zFileEngine::remove() +{ + return false; +} + +bool C7zFileEngine::mkdir(const QString& dirName, bool createParentDirectories) const +{ + return false; +} + +bool C7zFileEngine::rmdir(const QString& dirName, bool recurseParentDirectories) const +{ + return false; +} + +bool C7zFileEngine::caseSensitive() const +{ + return false; +} + +bool C7zFileEngine::isRelativePath() const +{ + return false; +} + +QAbstractFileEngine::Iterator *C7zFileEngine::beginEntryList(QDir::Filters filters, const QStringList &filterNames) +{ + QMutexLocker Lock(_pMutex); + + QStringList allEntries; + for (int i = 0; i < _pArchive->FileCount(); i++) { + QString Path = _pArchive->FileProperty(i, "Path").toString(); + if (!_filename.isEmpty()) { + if (!Path.startsWith(_filename)) + continue; + Path = Path.mid(_filename.length() + 1); + } + if (!Path.isEmpty() && !Path.contains("\\")) + allEntries.append(Path); + } + + return new C7zFileEngineIterator(filters, filterNames, allEntries); +} + +QAbstractFileEngine::FileFlags C7zFileEngine::fileFlags(FileFlags type) const +{ + return type & _flags; +} + +QString C7zFileEngine::fileName(FileName file) const +{ + return _filename; +} + +QDateTime C7zFileEngine::fileTime(FileTime time) const +{ + switch (time) + { + case QAbstractFileEngine::ModificationTime: + default: + return _datetime; + break; + }; +} + +void C7zFileEngine::setFileName(const QString& file) +{ + int pos = file.indexOf(":") + 2; + _filename = file.mid(pos); + + if (_filename.isEmpty()) { // root + _flags = ExistsFlag | DirectoryType | ReadOwnerPerm | ReadUserPerm | ReadGroupPerm | ReadOtherPerm; + return; + } + + QMutexLocker Lock(_pMutex); + _index = _pArchive->FindByPath(_filename); + if (_index != -1) { + _flags = ExistsFlag | ReadOwnerPerm | ReadUserPerm | ReadGroupPerm | ReadOtherPerm; + if (_pArchive->FileProperty(_index, "IsDir").toBool()) + _flags |= DirectoryType; + else + _flags |= FileType; + } +} + +bool C7zFileEngine::atEnd() const +{ + return _pos >= _data.size(); +} + +qint64 C7zFileEngine::read(char* data, qint64 maxlen) +{ + qint64 togo = qMin(maxlen, _size - _pos); + if (togo > 0) { + memcpy(data, _data.constData() + _pos, togo); + _pos += togo; + } + return togo; +} + +qint64 C7zFileEngine::readLine(char* data, qint64 maxlen) +{ + return -1; // todo +} + +qint64 C7zFileEngine::write(const char* data, qint64 len) +{ + return -1; +} + +bool C7zFileEngine::isOpened() const +{ + return _size != 0; +} + +QFile::FileError C7zFileEngine::error() const +{ + return QFile::UnspecifiedError; +} + +QString C7zFileEngine::errorString() const +{ + return ""; +} + +bool C7zFileEngine::supportsExtension(Extension extension) const +{ + return extension == QAbstractFileEngine::AtEndExtension; +} + + + +////////////////////////////////////////////////////////////////////////////////////////// +// C7zFileEngineHandler +// + +C7zFileEngineHandler::C7zFileEngineHandler(const QString& ArchivePath, const QString& Scheme, QObject* parent) + : QObject(parent), m_pArchive(NULL) +{ + CArchive* pArchive = new CArchive(ArchivePath); + if (pArchive->Open() > 0) + m_pArchive = pArchive; + else + delete pArchive; + m_Scheme = Scheme + ":"; +} + +C7zFileEngineHandler::~C7zFileEngineHandler() +{ + delete m_pArchive; +} + +QAbstractFileEngine* C7zFileEngineHandler::create(const QString& filename) const +{ + if (m_pArchive && filename.startsWith(m_Scheme)) + return new C7zFileEngine(filename, m_pArchive, &m_Mutex); + + return NULL; +} \ No newline at end of file diff --git a/SandboxiePlus/MiscHelpers/Archive/ArchiveFS.h b/SandboxiePlus/MiscHelpers/Archive/ArchiveFS.h new file mode 100644 index 00000000..d6a87962 --- /dev/null +++ b/SandboxiePlus/MiscHelpers/Archive/ArchiveFS.h @@ -0,0 +1,84 @@ +#pragma once +#include +#include "Archive.h" + +#include "../mischelpers_global.h" + +////////////////////////////////////////////////////////////////////////////////////////// +// C7zFileEngine +// + +class MISCHELPERS_EXPORT C7zFileEngine : public QAbstractFileEngine +{ +protected: + friend class C7zFileEngineHandler; + C7zFileEngine(const QString& filename, CArchive* pArchive, QMutex* pMutex); + +public: + virtual ~C7zFileEngine(); + + virtual bool open(QIODevice::OpenMode openMode); + virtual bool close(); + virtual bool flush(); + virtual qint64 size() const; + virtual qint64 pos() const; + virtual bool seek(qint64 pos); + virtual bool isSequential() const; + virtual bool remove(); + virtual bool mkdir(const QString& dirName, bool createParentDirectories) const; + virtual bool rmdir(const QString& dirName, bool recurseParentDirectories) const; + virtual bool caseSensitive() const; + virtual bool isRelativePath() const; + virtual FileFlags fileFlags(FileFlags type = FileInfoAll) const; + virtual QString fileName(FileName file = DefaultName) const; + virtual QDateTime fileTime(FileTime time) const; + virtual void setFileName(const QString& file); + bool atEnd() const; + + virtual qint64 read(char* data, qint64 maxlen); + virtual qint64 readLine(char* data, qint64 maxlen); + virtual qint64 write(const char* data, qint64 len); + + bool isOpened() const; + + QAbstractFileEngine::Iterator* beginEntryList(QDir::Filters filters, const QStringList& filterNames); + + QFile::FileError error() const; + QString errorString() const; + + virtual bool supportsExtension(Extension extension) const; + +private: + qint64 _size; + FileFlags _flags; + QString _filename; + QDateTime _datetime; + int _index; + + QByteArray _data; + qint64 _pos; + + CArchive* _pArchive; + QMutex* _pMutex; +}; + +////////////////////////////////////////////////////////////////////////////////////////// +// C7zFileEngineHandler +// + +class MISCHELPERS_EXPORT C7zFileEngineHandler : public QObject, public QAbstractFileEngineHandler +{ +public: + C7zFileEngineHandler(const QString& ArchivePath, const QString& Scheme, QObject* parent = NULL); + ~C7zFileEngineHandler(); + + bool IsOpen() { return m_pArchive != NULL; } + QString Prefix() { return m_Scheme; } + + QAbstractFileEngine* create(const QString& filename) const; + +private: + QString m_Scheme; + CArchive* m_pArchive; + mutable QMutex m_Mutex; +}; \ No newline at end of file diff --git a/SandboxiePlus/MiscHelpers/Archive/ArchiveHelper.cpp b/SandboxiePlus/MiscHelpers/Archive/ArchiveHelper.cpp new file mode 100644 index 00000000..a58ca5a7 --- /dev/null +++ b/SandboxiePlus/MiscHelpers/Archive/ArchiveHelper.cpp @@ -0,0 +1,156 @@ +#include "stdafx.h" + +#ifndef WIN32 +#define INITGUID +#endif + +#include "ArchiveHelper.h" + +#ifdef USE_7Z + +HRESULT GetCoderClass(GetMethodPropertyFunc getMethodProperty, UInt32 index, PROPID propId, CLSID &clsId, bool &isAssigned) +{ + NWindows::NCOM::CPropVariant prop; + isAssigned = false; + RINOK(getMethodProperty(index, propId, &prop)); + if (prop.vt == VT_BSTR) + { + isAssigned = true; + clsId = *(const GUID *)prop.bstrVal; + } + else if (prop.vt != VT_EMPTY) + return E_FAIL; + return S_OK; +} + +HRESULT ReadProp(GetHandlerPropertyFunc getProp, GetHandlerPropertyFunc2 getProp2, UInt32 index, PROPID propID, NWindows::NCOM::CPropVariant &prop) +{ + if (getProp2) + return getProp2(index, propID, &prop);; + return getProp(propID, &prop); +} + +HRESULT ReadStringProp(GetHandlerPropertyFunc getProp, GetHandlerPropertyFunc2 getProp2, UInt32 index, PROPID propID, QString &res) +{ + NWindows::NCOM::CPropVariant prop; + RINOK(ReadProp(getProp, getProp2, index, propID, prop)); + if (prop.vt == VT_BSTR) + res = QString::fromStdWString(prop.bstrVal ? prop.bstrVal : L""); + else if (prop.vt != VT_EMPTY) + return E_FAIL; + return S_OK; +} + +HRESULT ReadBoolProp(GetHandlerPropertyFunc getProp, GetHandlerPropertyFunc2 getProp2, UInt32 index, PROPID propID, bool &res) +{ + NWindows::NCOM::CPropVariant prop; + RINOK(ReadProp(getProp, getProp2, index, propID, prop)); + if (prop.vt == VT_BOOL) + res = VARIANT_BOOLToBool(prop.boolVal); + else if (prop.vt != VT_EMPTY) + return E_FAIL; + return S_OK; +} + +HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result) +{ + NWindows::NCOM::CPropVariant prop; + RINOK(archive->GetProperty(index, propID, &prop)); + if (prop.vt == VT_BOOL) + result = VARIANT_BOOLToBool(prop.boolVal); + else if (prop.vt == VT_EMPTY) + result = false; + else + return E_FAIL; + return S_OK; +} + +struct SPropertyNames{ + SPropertyNames(); + QMap Map; +} SPropertyNames; + + +SPropertyNames::SPropertyNames() +{ + Map.insert(kpidPath, "Path"); + Map.insert(kpidName, "Name"); + Map.insert(kpidExtension, "Extension"); + Map.insert(kpidIsDir, "IsDir"); + Map.insert(kpidSize, "Size"); + Map.insert(kpidPackSize, "PackSize"); + Map.insert(kpidAttrib, "Attrib"); + Map.insert(kpidCTime, "CTime"); + Map.insert(kpidATime, "ATime"); + Map.insert(kpidMTime, "MTime"); + Map.insert(kpidSolid, "Solid"); + Map.insert(kpidCommented, "Commented"); + Map.insert(kpidEncrypted, "Encrypted"); + Map.insert(kpidSplitBefore, "SplitBefore"); + Map.insert(kpidSplitAfter, "SplitAfter"); + Map.insert(kpidDictionarySize, "DictionarySize"); + Map.insert(kpidCRC, "CRC"); + Map.insert(kpidType, "Type"); + Map.insert(kpidIsAnti, "IsAnti"); + Map.insert(kpidMethod, "Method"); + Map.insert(kpidHostOS, "HostOS"); + Map.insert(kpidFileSystem, "FileSystem"); + Map.insert(kpidUser, "User"); + Map.insert(kpidGroup, "Group"); + Map.insert(kpidBlock, "Block"); + Map.insert(kpidComment, "Comment"); + Map.insert(kpidPosition, "Position"); + Map.insert(kpidPrefix, "Prefix"); + Map.insert(kpidNumSubDirs, "NumSubDirs"); + Map.insert(kpidNumSubFiles, "NumSubFiles"); + Map.insert(kpidUnpackVer, "UnpackVer"); + Map.insert(kpidVolume, "Volume"); + Map.insert(kpidIsVolume, "IsVolume"); + Map.insert(kpidOffset, "Offset"); + Map.insert(kpidLinks, "Links"); + Map.insert(kpidNumBlocks, "NumBlocks"); + Map.insert(kpidNumVolumes, "NumVolumes"); + + Map.insert(kpidBit64, "Bit64"); + Map.insert(kpidBigEndian, "BigEndian"); + Map.insert(kpidCpu, "Cpu"); + Map.insert(kpidPhySize, "PhySize"); + Map.insert(kpidHeadersSize, "HeadersSize"); + Map.insert(kpidChecksum, "Checksum"); + Map.insert(kpidCharacts, "Characts"); + Map.insert(kpidVa, "Va"); + Map.insert(kpidId, "Id"); + Map.insert(kpidShortName, "ShortName"); + Map.insert(kpidCreatorApp, "CreatorApp"); + Map.insert(kpidSectorSize, "SectorSize"); + Map.insert(kpidPosixAttrib, "PosixAttrib"); + Map.insert(kpidLink, "Link"); + Map.insert(kpidError, "Error"); + + Map.insert(kpidTotalSize, "TotalSize"); + Map.insert(kpidFreeSpace, "FreeSpace"); + Map.insert(kpidClusterSize, "ClusterSize"); + Map.insert(kpidVolumeName, "VolumeName"); + + Map.insert(kpidLocalName, "LocalName"); + Map.insert(kpidProvider, "Provider"); +}; + +QString GetPropertyName(PROPID PropID) +{ + return SPropertyNames.Map.value(PropID, "unknown"); +} + + +#if 1 +#include "./7z/CPP/Windows/PropVariant.cpp" +#else +#ifndef WIN32 +#include "../../7-Zip/p7zip_9.20.1/CPP/Windows/PropVariant.cpp" +#include "../../7-Zip/p7zip_9.20.1/CPP/Common/MyWindows.cpp" +#else +#include "../../7-Zip/7z/CPP/Windows/PropVariant.cpp" +#endif +#endif + +#endif \ No newline at end of file diff --git a/SandboxiePlus/MiscHelpers/Archive/ArchiveHelper.h b/SandboxiePlus/MiscHelpers/Archive/ArchiveHelper.h new file mode 100644 index 00000000..c9be04b2 --- /dev/null +++ b/SandboxiePlus/MiscHelpers/Archive/ArchiveHelper.h @@ -0,0 +1,85 @@ +#pragma once + +#include "Archive.h" + +#ifdef USE_7Z + +#if 1 +#include "./7z/CPP/Common/MyInitGuid.h" +#include "./7z/CPP/Common/MyCom.h" +#include "./7z/CPP/7zip/Archive/IArchive.h" +#include "./7z/CPP/7zip/IPassword.h" +#include "./7z/CPP/7zip/IProgress.h" +#include "./7z/CPP/Windows/PropVariant.h" +#include "./7z/CPP/Common/Defs.h" +#include "./7z/CPP/Windows/Defs.h" +#include "./7z/CPP/7zip/ICoder.h" +#else +#ifndef WIN32 +#include "../../7-Zip/p7zip_9.20.1/CPP/myWindows/StdAfx.h" +#include "../../7-Zip/p7zip_9.20.1/CPP/Common/MyCom.h" +#include "../../7-Zip/p7zip_9.20.1/CPP/Common/MyGuidDef.h" +#include "../../7-Zip/p7zip_9.20.1/CPP/7zip/Archive/IArchive.h" +#include "../../7-Zip/p7zip_9.20.1/CPP/7zip/IPassword.h" +#include "../../7-Zip/p7zip_9.20.1/CPP/7zip/IProgress.h" +#include "../../7-Zip/p7zip_9.20.1/CPP/Windows/PropVariant.h" +#include "../../7-Zip/p7zip_9.20.1/CPP/Common/Defs.h" +#include "../../7-Zip/p7zip_9.20.1/CPP/Windows/Defs.h" +#include "../../7-Zip/p7zip_9.20.1/CPP/7zip/ICoder.h" +#else +#include "../../7-Zip/7z920/CPP/Common/MyInitGuid.h" +#include "../../7-Zip/7z920/CPP/Common/MyCom.h" +#include "../../7-Zip/7z920/CPP/7zip/Archive/IArchive.h" +#include "../../7-Zip/7z920/CPP/7zip/IPassword.h" +#include "../../7-Zip/7z920/CPP/7zip/IProgress.h" +#include "../../7-Zip/7z920/CPP/Windows/PropVariant.h" +#include "../../7-Zip/7z920/CPP/Common/Defs.h" +#include "../../7-Zip/7z920/CPP/Windows/Defs.h" +#include "../../7-Zip/7z920/CPP/7zip/ICoder.h" +#endif +#endif + +#include + +#include "ArchiveIO.h" + +typedef UInt32 (WINAPI *GetMethodPropertyFunc)(UInt32 index, PROPID propID, PROPVARIANT *value); +typedef UInt32 (WINAPI *GetNumberOfMethodsFunc)(UInt32 *numMethods); + +typedef UInt32 (WINAPI *GetHandlerPropertyFunc)(PROPID propID, PROPVARIANT *value); +typedef UInt32 (WINAPI *GetHandlerPropertyFunc2)(UInt32 index, PROPID propID, PROPVARIANT *value); +typedef UInt32 (WINAPI *GetNumberOfFormatsFunc)(UInt32 *numFormats); + +typedef UInt32 (WINAPI *CreateObjectFunc)(const GUID *clsID, const GUID *interfaceID, void **outObject); + + +HRESULT GetCoderClass(GetMethodPropertyFunc getMethodProperty, UInt32 index, PROPID propId, CLSID &clsId, bool &isAssigned); +HRESULT ReadProp(GetHandlerPropertyFunc getProp, GetHandlerPropertyFunc2 getProp2, UInt32 index, PROPID propID, NWindows::NCOM::CPropVariant &prop); +HRESULT ReadStringProp(GetHandlerPropertyFunc getProp, GetHandlerPropertyFunc2 getProp2, UInt32 index, PROPID propID, QString &res); +HRESULT ReadBoolProp(GetHandlerPropertyFunc getProp, GetHandlerPropertyFunc2 getProp2, UInt32 index, PROPID propID, bool &res); +HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result); + +QString GetPropertyName(PROPID PropID); + +/* +DEFINE_GUID(CLSID_7z, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x07, 0x00, 0x00); // 7z - 7-Zip Arcive +DEFINE_GUID(CLSID_rar, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x03, 0x00, 0x00); // rar r00 - WinRar Archive +DEFINE_GUID(CLSID_cab, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x08, 0x00, 0x00); // cab - Cabinet File +DEFINE_GUID(CLSID_tar, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0xEE, 0x00, 0x00); // tar - Tar Archive +DEFINE_GUID(CLSID_zip, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x01, 0x00, 0x00); // zip jar xpi odt ods docx xlsx - Zip Archive +DEFINE_GUID(CLSID_hfs, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0xE3, 0x00, 0x00); // hfs - HFS Image +DEFINE_GUID(CLSID_iso, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0xE7, 0x00, 0x00); // iso img - ISO Image +DEFINE_GUID(CLSID_udf, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0xE0, 0x00, 0x00); // iso img - UDF Image +DEFINE_GUID(CLSID_wim, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0xE6, 0x00, 0x00); // wim swm - Windows Image +DEFINE_GUID(CLSID_chm, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0xE9, 0x00, 0x00); // chm chi chq chw hxs hxi hxr hxq hxw lit - Compressed HTML Help +DEFINE_GUID(CLSID_msi, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0xE5, 0x00, 0x00); // msi msp doc xls ppt - Microsoft Installer +DEFINE_GUID(CLSID_nsis, 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x09, 0x00, 0x00); // - Nullsoft Scriptable Install System +*/ + +#ifndef TRACE +#define TRACE +#endif + +#define QS2CS(x) (x.toLatin1().data()) + +#endif \ No newline at end of file diff --git a/SandboxiePlus/MiscHelpers/Archive/ArchiveIO.h b/SandboxiePlus/MiscHelpers/Archive/ArchiveIO.h new file mode 100644 index 00000000..90b91d48 --- /dev/null +++ b/SandboxiePlus/MiscHelpers/Archive/ArchiveIO.h @@ -0,0 +1,84 @@ +#pragma once + +#include "ArchiveHelper.h" + +#ifdef USE_7Z + +class CArchiveIO: public IOutStream, public IInStream, public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP2(IOutStream, IInStream) + + CArchiveIO(QIODevice* pFile, QIODevice::OpenMode Mode, bool bDelete = true) + { + Q_ASSERT(pFile); + m_pFile = pFile; + if(Mode != QIODevice::NotOpen) + m_pFile->open(Mode); + m_bDelete = bDelete; + } + ~CArchiveIO() + { + m_pFile->close(); + if(m_bDelete) + delete m_pFile; + } + + bool Open(QIODevice::OpenMode Mode) { + return m_pFile->open(Mode); + } + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) + { + quint64 read = m_pFile->read((char*)data, size); + if(read == -1) + return E_FAIL; + if(processedSize) + *processedSize = read; + return S_OK; + } + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize) + { + quint64 writen = m_pFile->write((const char*)data, size); + if(writen == -1) + return E_FAIL; + if(processedSize) + *processedSize = writen; + return S_OK; + } + + STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) + { + switch(seekOrigin) + { + case 0: break; // FILE_BEGIN + case 1: offset += m_pFile->pos(); break; // FILE_CURRENT + case 2: offset += m_pFile->size(); break; // FILE_END + default: Q_ASSERT(0); return E_FAIL; + } + + if(!m_pFile->seek(offset)) + return E_FAIL; + if(newPosition) + *newPosition = offset; + return S_OK; + } + + STDMETHOD(SetSize)(UInt64 newSize) + { + return S_OK; + } + + STDMETHOD(GetSize)(UInt64 *size) + { + *size = m_pFile->size(); + return S_OK; + } + +protected: + QIODevice* m_pFile; + bool m_bDelete; +}; + +#endif \ No newline at end of file diff --git a/SandboxiePlus/MiscHelpers/Archive/ArchiveInterface.cpp b/SandboxiePlus/MiscHelpers/Archive/ArchiveInterface.cpp new file mode 100644 index 00000000..771fb0f0 --- /dev/null +++ b/SandboxiePlus/MiscHelpers/Archive/ArchiveInterface.cpp @@ -0,0 +1,193 @@ +#include "stdafx.h" +#include "ArchiveInterface.h" +//#include "../Functions.h" +#ifdef __APPLE__ +#include +#endif + +#ifdef USE_7Z + +CArchiveInterface::CArchiveInterface() +: m_7z("7z") +{ + m_Operational = false; +} + +bool CArchiveInterface::Init() +{ + QMutexLocker Locker(&m_Mutex); + + if(m_Operational) + return true; + +#ifdef __APPLE__ + m_7z.setFileName(QCoreApplication::applicationDirPath() + "/7z.so"); +#endif + + //LogLine(LOG_INFO | LOG_DEBUG, QObject::tr("7z: Loading Library...")); + if(!m_7z.load()) + { + //LogLine(LOG_ERROR | LOG_DEBUG, QObject::tr("7z: failed to load!")); + return false; + } + + // Load Available Coders + /*GetMethodPropertyFunc getMethodPropertyFunc = (GetMethodPropertyFunc)m_7z.resolve("GetMethodProperty"); + GetNumberOfMethodsFunc getNumberOfMethodsFunc = (GetNumberOfMethodsFunc)m_7z.resolve("GetNumberOfMethods"); + if(!getNumberOfMethodsFunc || !getMethodPropertyFunc) + return false; + + UInt32 numMethods = 1; + if(getNumberOfMethodsFunc(&numMethods) != S_OK) + return false; + + for(UInt32 i = 0; i < numMethods; i++) + { + CCdrInfo info; + info.Index = i; + Q_ASSERT(GetCoderClass(getMethodPropertyFunc, i, NMethodPropID::kEncoder, info.Encoder, info.EncoderIsAssigned) == S_OK); + Q_ASSERT(GetCoderClass(getMethodPropertyFunc, i, NMethodPropID::kDecoder, info.Decoder, info.DecoderIsAssigned) == S_OK); + m_Coders.append(info); + }*/ + + // Load Supported Formats + GetHandlerPropertyFunc getProp = NULL; + GetHandlerPropertyFunc2 getProp2 = (GetHandlerPropertyFunc2)m_7z.resolve("GetHandlerProperty2"); + if (getProp2 == NULL) + { + getProp = (GetHandlerPropertyFunc)m_7z.resolve("GetHandlerProperty"); + if(!getProp) + { + //LogLine(LOG_ERROR | LOG_DEBUG, QObject::tr("7z: Failed to resolve GetHandlerProperty!")); + return false; + } + } + + UInt32 numFormats = 1; + GetNumberOfFormatsFunc getNumberOfFormats = (GetNumberOfFormatsFunc)m_7z.resolve("GetNumberOfFormats"); + if (getNumberOfFormats != NULL) + { + if(getNumberOfFormats(&numFormats) != S_OK) + { + //LogLine(LOG_ERROR | LOG_DEBUG, QObject::tr("7z: Failed to enumerate Formats!")); + return false; + } + } + if (getProp2 == NULL) + numFormats = 1; + + for(UInt32 i = 0; i < numFormats; i++) + { + CArcInfoEx info; + + if(ReadStringProp(getProp, getProp2, i, NArchive::kName, info.Name) != S_OK) + { + //LogLine(LOG_ERROR | LOG_DEBUG, QObject::tr("7z: Failed to get Formats %1 Name!").arg(i)); + return false; + } + + NWindows::NCOM::CPropVariant prop; + if (ReadProp(getProp, getProp2, i, NArchive::kClassID, prop) != S_OK) + continue; + if (prop.vt != VT_BSTR) + continue; + info.ClassID = *(const GUID *)prop.bstrVal; + prop.Clear(); + + QString ext, addExt; + if(ReadStringProp(getProp, getProp2, i, NArchive::kExtension, ext) != S_OK) + { + //LogLine(LOG_ERROR | LOG_DEBUG, QObject::tr("7z: Failed to get Formats %1 Property kExtension!").arg(i)); + return false; + } + if(ReadStringProp(getProp, getProp2, i, NArchive::kAddExtension, addExt) != S_OK) + { + //LogLine(LOG_ERROR | LOG_DEBUG, QObject::tr("7z: Failed to get Formats %1 Property kAddExtension!").arg(i)); + return false; + } + info.AddExts(ext, addExt); + + //TRACE(L"Archive Format %S supported %S, %S", QS2CS(info.Name), QS2CS(ext), QS2CS(addExt)); + + ReadBoolProp(getProp, getProp2, i, NArchive::kUpdate, info.UpdateEnabled); + if (info.UpdateEnabled) + ReadBoolProp(getProp, getProp2, i, NArchive::kKeepName, info.KeepName); + +#ifdef _SFX + if (ReadProp(getProp, getProp2, i, NArchive::kStartSignature, prop) == S_OK) + { + if (prop.vt == VT_BSTR) + info.StartSignature = QByteArray((char*)prop.bstrVal, ::SysStringByteLen(prop.bstrVal)); + } +#endif + + m_Formats.append(info); + } + + createObjectFunc = (CreateObjectFunc)m_7z.resolve("CreateObject"); + if(createObjectFunc == NULL) + { + //LogLine(LOG_ERROR | LOG_DEBUG, QObject::tr("7z: Failed to resolve CreateObjectFunc!")); + return false; + } + + //LogLine(LOG_SUCCESS | LOG_DEBUG, QObject::tr("7z: Loaded Successfuly")); + m_Operational = true; + return true; +} + +int CArchiveInterface::FindByExt(const QString &Ext) const +{ + QMutexLocker Locker(&m_Mutex); + for(int i=0; i CArchiveInterface::FindByExt(const QString &Ext) +{ + QMutexLocker Locker(&m_Mutex); + QList ArcIndex; + for(int i=0; i 0 && formatIndex <= m_Formats.count()) + return m_Formats[formatIndex-1].Name; + return ""; +} + +bool CArchiveInterface::CreateInArchive(int formatIndex, CMyComPtr &archive) const +{ + QMutexLocker Locker(&m_Mutex); + if(formatIndex > 0 && formatIndex <= m_Formats.count()) + return CreateArchiveHandler(m_Formats[formatIndex-1], (void **)&archive, false); + return false; +} + +bool CArchiveInterface::CreateOutArchive(int formatIndex, CMyComPtr &archive) const +{ + QMutexLocker Locker(&m_Mutex); + if(formatIndex > 0 && formatIndex <= m_Formats.count()) + return CreateArchiveHandler(m_Formats[formatIndex-1], (void **)&archive, true); + return false; +} + +bool CArchiveInterface::CreateArchiveHandler(const CArcInfoEx &ai, void **archive, bool outHandler) const +{ + if(createObjectFunc) + return createObjectFunc(&ai.ClassID, outHandler ? &IID_IOutArchive : &IID_IInArchive, (void **)archive) == S_OK; + return false; +} + +#endif \ No newline at end of file diff --git a/SandboxiePlus/MiscHelpers/Archive/ArchiveInterface.h b/SandboxiePlus/MiscHelpers/Archive/ArchiveInterface.h new file mode 100644 index 00000000..d1e03c68 --- /dev/null +++ b/SandboxiePlus/MiscHelpers/Archive/ArchiveInterface.h @@ -0,0 +1,114 @@ +#pragma once + +#include "ArchiveHelper.h" + +#ifdef USE_7Z + + +/*struct CCdrInfo +{ + UInt32 Index; + CLSID Encoder; + CLSID Decoder; + bool EncoderIsAssigned; + bool DecoderIsAssigned; +};*/ + +struct CArcInfoEx +{ + CArcInfoEx(): UpdateEnabled(false), KeepName(false) {} + + CLSID ClassID; + QString Name; + + bool UpdateEnabled; + bool KeepName; + + struct CArcExtInfo + { + CArcExtInfo(const QString ext = "", const QString addExt = ""): Ext(ext), AddExt(addExt) {} + QString Ext; + QString AddExt; + }; + QList Exts; + +#ifdef _SFX + QByteArray StartSignature; + // CByteBuffer FinishSignature; +#endif + + QString GetMainExt() const + { + if (Exts.isEmpty()) + return ""; + return Exts[0].Ext; + } + int FindExtension(const QString &ext) const + { + for (int i = 0; i < Exts.count(); i++) + if (ext.compare(Exts[i].Ext, Qt::CaseInsensitive) == 0) + return i; + return -1; + } + QString GetAllExtensions() const + { + QString s; + for (int i = 0; i < Exts.count(); i++) + { + if (i > 0) + s += ' '; + s += Exts[i].Ext; + } + return s; + } + void AddExts(const QString &ext, const QString &addExt) + { + QStringList exts = ext.split(" "); + exts.removeAll(""); + QStringList addExts = addExt.split(" "); + addExts.removeAll(""); + for (int i = 0; i < exts.count(); i++) + { + CArcExtInfo extInfo; + extInfo.Ext = exts[i]; + if (i < addExts.count()) + { + extInfo.AddExt = addExts[i]; + if (extInfo.AddExt == "*") + extInfo.AddExt.clear(); + } + Exts.append(extInfo); + } + } +}; + + +class CArchiveInterface +{ +public: + CArchiveInterface(); + bool Init(); + + bool IsOperational() {return m_Operational;} + + int FindByExt(const QString &Ext) const; + //QList FindByExt(const QString &Ext); + QString GetArchiveName(int formatIndex); + + int GetFormatCount() {return m_Formats.count();} + bool CreateInArchive(int formatIndex, CMyComPtr &archive) const; + bool CreateOutArchive(int formatIndex, CMyComPtr &archive) const; + +protected: + bool CreateArchiveHandler(const CArcInfoEx &ai, void **archive, bool outHandler) const; + + QLibrary m_7z; + //QList m_Coders; + QVector m_Formats; + CreateObjectFunc createObjectFunc; + + bool m_Operational; + mutable QMutex m_Mutex; +}; + +#endif diff --git a/SandboxiePlus/MiscHelpers/Archive/ArchiveOpener.cpp b/SandboxiePlus/MiscHelpers/Archive/ArchiveOpener.cpp new file mode 100644 index 00000000..6639cdb0 --- /dev/null +++ b/SandboxiePlus/MiscHelpers/Archive/ArchiveOpener.cpp @@ -0,0 +1,53 @@ +#include "stdafx.h" +#include "ArchiveOpener.h" +#include "Archive.h" + +#ifdef USE_7Z + +CArchiveOpener::CArchiveOpener(CArchive* pArchive) +{ + m_pArchive = pArchive; +} + +STDMETHODIMP CArchiveOpener::GetProperty(PROPID propID, PROPVARIANT *value) +{ + NWindows::NCOM::CPropVariant prop; + switch(propID) + { + case kpidName: + { + QString Name = m_pArchive->m_ArchivePath; + int Pos = m_pArchive->m_ArchivePath.lastIndexOf("/"); + if(Pos != -1) + Name.remove(0,Pos+1); + + prop = Name.toStdWString().c_str(); break; + } + default: Q_ASSERT(0); + } + prop.Detach(value); + return S_OK; +} + +STDMETHODIMP CArchiveOpener::GetStream(const wchar_t *name, IInStream **inStream) +{ + m_pArchive->SetPartSize(0); // tell that this is multipart + QString Path = m_pArchive->GetNextPart(QString::fromStdWString(name)); + if(QFile::exists(Path)) + { + CMyComPtr inStreamLoc(new CArchiveIO(new QFile(Path), QIODevice::ReadOnly)); + *inStream = inStreamLoc.Detach(); + return S_OK; + } + return S_FALSE; +} + +STDMETHODIMP CArchiveOpener::CryptoGetTextPassword(BSTR *password) +{ + QString Password = m_pArchive->GetPassword(true); + if(Password.isEmpty()) + return E_ABORT; + return StringToBstr(Password.toStdWString().c_str(), password); +} + +#endif \ No newline at end of file diff --git a/SandboxiePlus/MiscHelpers/Archive/ArchiveOpener.h b/SandboxiePlus/MiscHelpers/Archive/ArchiveOpener.h new file mode 100644 index 00000000..539be074 --- /dev/null +++ b/SandboxiePlus/MiscHelpers/Archive/ArchiveOpener.h @@ -0,0 +1,29 @@ +#pragma once + +#include "ArchiveHelper.h" + +#ifdef USE_7Z + +class CArchiveOpener: public IArchiveOpenCallback, public IArchiveOpenVolumeCallback, public ICryptoGetTextPassword, public CMyUnknownImp +{ +public: + CArchiveOpener(CArchive* pArchive); + + MY_UNKNOWN_IMP3(IArchiveOpenCallback, IArchiveOpenVolumeCallback, ICryptoGetTextPassword) + + // IArchiveOpenCallback + STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes) {return S_OK;} + STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes) {return S_OK;} + + // IArchiveOpenVolumeCallback + STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value); + STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream); + + // ICryptoGetTextPassword2 + STDMETHOD(CryptoGetTextPassword)(BSTR *password); + +protected: + CArchive* m_pArchive; +}; + +#endif \ No newline at end of file diff --git a/SandboxiePlus/MiscHelpers/Archive/ArchiveThread.cpp b/SandboxiePlus/MiscHelpers/Archive/ArchiveThread.cpp new file mode 100644 index 00000000..9bbd4f4f --- /dev/null +++ b/SandboxiePlus/MiscHelpers/Archive/ArchiveThread.cpp @@ -0,0 +1,419 @@ +#include "stdafx.h" +#include "ArchiveThread.h" +#include "SplitFile.h" +#include "../Common/Common.h" +#include "../Common/OtherFunctions.h" + +int _QStringList_pType = qRegisterMetaType("QStringList"); + +CArchiveThread::CArchiveThread(const QString &ArchivePath, const QString &WorkingPath, const QString &Password, quint64 PartSize, const QStringList& Parts) +{ +#ifdef USE_7Z + m_Worker = new C7zWorker(ArchivePath, WorkingPath, Password, PartSize, Parts); + m_Worker->moveToThread(this); + start(); + m_Worker->m_Lock.Lock(); +#else + ASSERT(0); +#endif +} + +CArchiveThread::CArchiveThread(const QString &WinRarPath, const QString &ArchivePath, const QString &WorkingPath, const QString &Password, quint64 PartSize, const QString &CommentPath) +{ + m_Worker = new CRarWorker(WinRarPath, ArchivePath, WorkingPath, Password, PartSize, CommentPath); + m_Worker->moveToThread(this); + start(); + m_Worker->m_Lock.Lock(); +} + +void CArchiveThread::Terminate() +{ + stop(); + delete m_Worker; + delete this; +} + +QStringList CArchiveThread::ListParts(const QString &ArchivePath, bool NamesOnly) +{ + QStringList Parts; + + StrPair PathName = Split2(ArchivePath, "/", true); + StrPair NameEx = Split2(PathName.second, ".", true); + QString PatternStr; + if(NameEx.second == "rar") + PatternStr = QRegularExpression::escape(NameEx.first) + "(\\.part[0-9]*)?\\.rar"; + else + PatternStr = QRegularExpression::escape(NameEx.first + "." + NameEx.second) + "(\\.[0-9]*)?"; + QRegularExpression Pattern = QRegularExpression(QRegularExpression::anchoredPattern(PatternStr), QRegularExpression::CaseInsensitiveOption); + + QDir Dir(PathName.first); + foreach (const QString& File, Dir.entryList()) + { + if (File.compare(".") == 0 || File.compare("..") == 0) + continue; + QRegularExpressionMatch Result = Pattern.match(File); + if(Result.hasMatch()) + { + if(NamesOnly) + Parts.append(File); + else + Parts.append(PathName.first + "/" + File); + } + } + return Parts; +} + +QStringList CArchiveThread::GetErrors() +{ + QStringList Errors; + if(IsBusy()) + return Errors; + Errors = m_Worker->m_Errors; + if(!Errors.isEmpty() && HasUsedPassword()) + Errors.append("Wrong Password ?"); + m_Worker->m_Errors.clear(); + return Errors; +} + +////////////////////////////////////////////////////////////////////////// +// Buildin 7z Library worker +// + +#ifdef USE_7Z + +C7zWorker::C7zWorker(const QString &ArchivePath, const QString &WorkingPath, const QString &Password, quint64 PartSize, const QStringList& Parts) +: CArchive(ArchivePath) +{ + SetPassword(Password); + SetPartSize(PartSize); + m_WorkingPath = WorkingPath; + SetPartList(Parts); + + if(QFile::exists(ArchivePath)) + { + if(!Open()) + m_Errors.append("Open Failed"); + } +} + +C7zWorker::~C7zWorker() +{ + Close(); +} + +QMap C7zWorker::GetFileList() +{ + QMap FileList; + if(!m_Mutex.tryLock(100)) + { + //LogLine(LOG_DEBUG | LOG_ERROR, tr("atempted to get the file list of a already busy archive thread")); + return FileList; + } + + if(m_Archive) + { + foreach(const SFile& File, m_Files) + { + if(File.Properties["IsDir"].toBool()) + continue; + FileList.insert(File.Properties["Path"].toString(), File.Properties["Size"].toULongLong()); + } + } + //else + //LogLine(LOG_DEBUG | LOG_ERROR, tr("Archive %1, is not open for extraction").arg(m_ArchivePath)); + + m_Mutex.unlock(); + return FileList; +} + +void C7zWorker::OnExtractAllFiles() +{ + QMutexLocker Locker(&m_Mutex); + m_Lock.Release(); + + SArcInfo Info = GetArcInfo(m_ArchivePath); + if(Info.FormatIndex == 0) // not an arcive just a split file + { + if(!QDir().exists(m_WorkingPath)) + QDir().mkpath(m_WorkingPath); + + if(Info.PartNumber == -1) // single aprt + { + if(!QFile::rename(m_ArchivePath,m_WorkingPath + Info.FileName)) + m_Errors.append("Failed to move file"); + } + else // multi part, to be merged + { + int Pos = m_ArchivePath.indexOf(QRegularExpression("\\.[0-9]+$")); + if(Pos != -1) + m_ArchivePath.truncate(Pos); + + CSplitFile SplitFile(m_ArchivePath); + if(!SplitFile.open(QIODevice::ReadOnly)) + m_Errors.append("Failed to open temp file"); + else + { + QFile File(m_WorkingPath + Info.FileName); + if(!File.open(QIODevice::WriteOnly)) + m_Errors.append("Failed to open file"); + else + { + const qint64 Size = 16*1024; + char Buffer[Size]; + while(!SplitFile.atEnd()) + { + qint64 Temp = SplitFile.read(Buffer, Size); + File.write(Buffer, Temp); + } + } + } + } + } + else + + if(!Extract(m_WorkingPath)) + m_Errors.append("Extraction Failed"); +} + +void C7zWorker::OnInsertAllFiles() +{ + OnInsertFiles(ListDir(m_WorkingPath)); +} + +void C7zWorker::OnExtractFiles(QStringList FileList) +{ + QMutexLocker Locker(&m_Mutex); + m_Lock.Release(); + + if(!QDir().exists(m_WorkingPath)) + QDir().mkpath(m_WorkingPath); + + QMap Files; + foreach(const QString& Name, FileList) + { + int ArcIndex = FindByPath(Name); + if(ArcIndex != -1) + Files.insert(ArcIndex, new QFile(PrepareExtraction(Name, m_WorkingPath))); + //else + //LogLine(LOG_DEBUG, tr("file %1 couldn't be find in archive %2").arg(Name, m_ArchivePath)); // should not happen + } + + if(!Extract(&Files)) + m_Errors.append("Extraction Failed"); +} + +void C7zWorker::OnInsertFiles(QStringList FileList) +{ + QMutexLocker Locker(&m_Mutex); + m_Lock.Release(); + + QMap Files; + foreach(const QString& File, FileList) + { + StrPair RootName = Split2(File, "\\", true); + if(RootName.second.isEmpty()) + { + RootName.second = RootName.first; + RootName.first = ""; + } + int ArcIndex = AddFile(RootName.second); + if(ArcIndex != -1) + { + QString FileName = (RootName.first.isEmpty() ? m_WorkingPath : RootName.first) + RootName.second; + Files.insert(ArcIndex, new QFile(FileName)); + } + //else + //LogLine(LOG_DEBUG, tr("file %1 is already present in archive %2").arg(RootName.second, m_ArchivePath)); // should not happen + } + + if(!Update(&Files)) + m_Errors.append("Insertion Failed"); +} + +#endif + +////////////////////////////////////////////////////////////////////////// +// Extern WinRar worker +// + +CRarWorker::CRarWorker(const QString &WinRarPath, const QString &ArchivePath, const QString &WorkingPath, const QString &Password, quint64 PartSize, const QString &CommentPath) +{ + m_WinRarPath = WinRarPath; + if(CommentPath.contains(" ")) + m_CommentPath = "\"" + CommentPath + "\""; + else + m_CommentPath = CommentPath; + + m_ArchivePath = ArchivePath; + m_WorkingPath = WorkingPath; + CreateDir(m_WorkingPath); + m_Password = Password; + m_PartSize = PartSize; + + if(!QFile::exists(WinRarPath + "rar.exe")) + m_Errors.append("WinRar is not present or the path is wrong"); +} + +QMap CRarWorker::GetFileList() +{ + QMap FileList; + if(!m_Mutex.tryLock(100)) + { + //LogLine(LOG_DEBUG | LOG_ERROR, tr("atempted to get the file list of a already busy archive thread")); + return FileList; + } + + QStringList Arguments; + Arguments.append("v"); + if(!m_Password.isEmpty()) + Arguments.append("-p" + m_Password); + Arguments.append(m_ArchivePath); + + QProcess* pWinRar = new QProcess(this); + pWinRar->start(m_WinRarPath + "unrar.exe", Arguments); + /*for(;;) + { + bool bDone = pWinRar->waitForFinished(1000); + QStringList Test; + while(pWinRar->canReadLine()) + { + QString Line = pWinRar->readLine(); + Test.append(Line); + } + if(bDone) + break; + }*/ + pWinRar->waitForFinished(-1); + QStringList Test; + int Index = -1; + QString Name; + while(pWinRar->canReadLine()) + { + QString Line = pWinRar->readLine().trimmed(); + if(Line == "-------------------------------------------------------------------------------") + { + if(Index == -1) + { + Index = 0; + continue; + } + break; + } + else if(Index == -1) + continue; + Index++; + + if(Index % 2 == 1) + Name = Line.replace("\\","/"); + else + FileList.insert(Name,Split2(Line," ").first.toULongLong()); + } + delete pWinRar; + + m_Mutex.unlock(); + return FileList; +} + +void CRarWorker::OnExtractAllFiles() +{ + QMutexLocker Locker(&m_Mutex); + m_Lock.Release(); + + QStringList Arguments; + Arguments.append("x"); + if(!m_Password.isEmpty()) + Arguments.append("-p" + m_Password); + Arguments.append(m_ArchivePath); + Arguments.append(m_WorkingPath); + + QProcess* pWinRar = new QProcess(this); + pWinRar->start(m_WinRarPath + "unrar.exe", Arguments); + pWinRar->waitForFinished(-1); + if(int ExitCode = pWinRar->exitCode()) + m_Errors.append(QString("WinRar returrned error code %1").arg(ExitCode)); + delete pWinRar; +} + +void CRarWorker::OnInsertAllFiles() +{ + QMutexLocker Locker(&m_Mutex); + m_Lock.Release(); + + QStringList Arguments; + Arguments.append("a"); + Arguments.append("-m0"); + if(!m_Password.isEmpty()) + Arguments.append("-hp" + m_Password); + if(m_PartSize != -1) + Arguments.append("-v" + QString::number(m_PartSize) + "b"); + if(!m_CommentPath.isEmpty()) + Arguments.append("-z" + m_CommentPath); + Arguments.append(m_ArchivePath); + Arguments.append(m_WorkingPath); + + QProcess* pWinRar = new QProcess(this); + pWinRar->start(m_WinRarPath + "rar.exe", Arguments); + pWinRar->waitForFinished(-1); + if(int ExitCode = pWinRar->exitCode()) + m_Errors.append(QString("WinRar returrned error code %1").arg(ExitCode)); + delete pWinRar; +} + +void CRarWorker::OnExtractFiles(QStringList FileList) +{ + QMutexLocker Locker(&m_Mutex); + m_Lock.Release(); + + QStringList Arguments; + Arguments.append("x"); + if(!m_Password.isEmpty()) + Arguments.append("-p" + m_Password); + Arguments.append(m_ArchivePath); + foreach(const QString& File, FileList) + Arguments.append(File); + Arguments.append(m_WorkingPath); + + QProcess* pWinRar = new QProcess(this); + pWinRar->start(m_WinRarPath + "unrar.exe", Arguments); + pWinRar->waitForFinished(-1); + if(int ExitCode = pWinRar->exitCode()) + m_Errors.append(QString("WinRar returrned error code %1").arg(ExitCode)); + delete pWinRar; +} + +void CRarWorker::OnInsertFiles(QStringList FileList) +{ + QMutexLocker Locker(&m_Mutex); + m_Lock.Release(); + + QStringList Arguments; + Arguments.append("a"); + Arguments.append("-m0"); + Arguments.append("-ep"); + Arguments.append("-ap" + Split2(Split2(m_ArchivePath, "/", true).second, ".", true).first.replace(" ", "_")); + if(!m_Password.isEmpty()) + Arguments.append("-hp" + m_Password); + if(m_PartSize != -1) + Arguments.append("-v" + QString::number(m_PartSize) + "b"); + if(!m_CommentPath.isEmpty()) + Arguments.append("-z" + m_CommentPath); + Arguments.append(m_ArchivePath); + foreach(const QString& File, FileList) + { + StrPair RootName = Split2(File, "\\", true); + if(RootName.second.isEmpty()) + { + RootName.second = RootName.first; + RootName.first = ""; + } + QString FileName = (RootName.first.isEmpty() ? m_WorkingPath : RootName.first) + RootName.second; + Arguments.append(FileName); + } + + QProcess* pWinRar = new QProcess(this); + pWinRar->start(m_WinRarPath + "rar.exe", Arguments); + pWinRar->waitForFinished(-1); + if(int ExitCode = pWinRar->exitCode()) + m_Errors.append(QString("WinRar returrned error code %1").arg(ExitCode)); + delete pWinRar; +} \ No newline at end of file diff --git a/SandboxiePlus/MiscHelpers/Archive/ArchiveThread.h b/SandboxiePlus/MiscHelpers/Archive/ArchiveThread.h new file mode 100644 index 00000000..7fdc3d51 --- /dev/null +++ b/SandboxiePlus/MiscHelpers/Archive/ArchiveThread.h @@ -0,0 +1,147 @@ +#pragma once + +#include "../mischelpers_global.h" + +#include "../Common/MT/ThreadLock.h" +#include "Archive.h" + +class CArchiveWorker: public QObject +{ + Q_OBJECT + +public: + + virtual double GetProgress() = 0; + virtual const QString& GetArchivePath() = 0; + virtual quint64 GetPartSize() = 0; + virtual QString GetPassword() = 0; + virtual bool HasUsedPassword() = 0; + + virtual QMap GetFileList() = 0; + +public slots: + virtual void OnExtractAllFiles() = 0; + virtual void OnInsertAllFiles() = 0; + virtual void OnExtractFiles(QStringList FileList) = 0; + virtual void OnInsertFiles(QStringList FileList) = 0; + +protected: + friend class CArchiveThread; + + virtual void LogError(const QString &Error) {m_Errors.append(Error);} + + QMutex m_Mutex; + CThreadLock m_Lock; + QString m_WorkingPath; + + QStringList m_Errors; +}; + +class MISCHELPERS_EXPORT CArchiveThread: public QThread +{ + Q_OBJECT + +public: + CArchiveThread(const QString &ArchivePath, const QString &WorkingPath, const QString &Password = QString(), quint64 PartSize = -1, const QStringList& Parts = QStringList()); + CArchiveThread(const QString &WinRarPath, const QString &ArchivePath, const QString &WorkingPath, const QString &Password = QString(), quint64 PartSize = -1, const QString &CommentPath = ""); + void Terminate(); + + static QStringList ListParts(const QString &ArchivePath, bool NamesOnly = false); + QMap GetFileList() {return m_Worker->GetFileList();} + + void ExtractAllFiles() {m_Worker->m_Lock.Reset(); emit AsyncExtractAllFiles(); m_Worker->m_Lock.Lock();} + void InsertAllFiles() {m_Worker->m_Lock.Reset(); emit AsyncInsertAllFiles(); m_Worker->m_Lock.Lock();} + void ExtractFiles(QStringList FileList) {m_Worker->m_Lock.Reset(); emit AsyncExtractFiles(FileList);m_Worker->m_Lock.Lock();} // paths in archive + void InsertFiles(QStringList FileList) {m_Worker->m_Lock.Reset(); emit AsyncInsertFiles(FileList); m_Worker->m_Lock.Lock();} // paths relative to the WorkingPath + + bool IsBusy() {if(!m_Worker->m_Mutex.tryLock()) return true; m_Worker->m_Mutex.unlock(); return false;} + double GetProgress() {return m_Worker->GetProgress();} + QStringList GetArchiveParts(bool NamesOnly = false) {return ListParts(m_Worker->GetArchivePath(), NamesOnly);} + quint64 GetPartSize() {return m_Worker->GetPartSize();} + QStringList GetErrors(); + bool HasUsedPassword() {return m_Worker->HasUsedPassword();} + QString GetPassword() {return m_Worker->GetPassword();} + + void run() + { + connect(this, SIGNAL(AsyncExtractAllFiles()), m_Worker, SLOT(OnExtractAllFiles())); + connect(this, SIGNAL(AsyncInsertAllFiles()), m_Worker, SLOT(OnInsertAllFiles())); + connect(this, SIGNAL(AsyncExtractFiles(QStringList)), m_Worker, SLOT(OnExtractFiles(QStringList))); + connect(this, SIGNAL(AsyncInsertFiles(QStringList)), m_Worker, SLOT(OnInsertFiles(QStringList))); + m_Worker->m_Lock.Release(); + exec(); + } + + void stop() + { + quit(); + wait(); + } + +signals: + void AsyncExtractAllFiles(); + void AsyncInsertAllFiles(); + void AsyncExtractFiles(QStringList FileList); + void AsyncInsertFiles(QStringList FileList); + +protected: + CArchiveWorker* m_Worker; +}; + +#ifdef USE_7Z + +class MISCHELPERS_EXPORT C7zWorker: public CArchiveWorker, protected CArchive +{ + Q_OBJECT + +public: + C7zWorker(const QString &ArchivePath, const QString &WorkingPath, const QString &Password = QString(), quint64 PartSize = -1, const QStringList& Parts = QStringList()); + ~C7zWorker(); + + virtual double GetProgress() {return CArchive::GetProgress();} + virtual const QString& GetArchivePath() {return CArchive::GetArchivePath();} + quint64 GetPartSize() {return CArchive::GetPartSize();} + virtual bool HasUsedPassword() {return CArchive::HasUsedPassword();} + virtual QString GetPassword() {return CArchive::GetPassword();} + + virtual QMap GetFileList(); + +public slots: + virtual void OnExtractAllFiles(); + virtual void OnInsertAllFiles(); + virtual void OnExtractFiles(QStringList FileList); + virtual void OnInsertFiles(QStringList FileList); + +}; + +#endif + +class MISCHELPERS_EXPORT CRarWorker: public CArchiveWorker +{ + Q_OBJECT + +public: + CRarWorker(const QString &WinRarPath, const QString &ArchivePath, const QString &WorkingPath, const QString &Password = QString(), quint64 PartSize = -1, const QString &CommentPath = ""); + + virtual double GetProgress() {return 0;} + virtual const QString& GetArchivePath() {return m_ArchivePath;} + quint64 GetPartSize() {return m_PartSize;} + virtual bool HasUsedPassword() {ASSERT(0); return false;} // rar should notbe used for unpacking + virtual QString GetPassword() {return m_Password;} + + virtual QMap GetFileList(); + +public slots: + virtual void OnExtractAllFiles(); + virtual void OnInsertAllFiles(); + virtual void OnExtractFiles(QStringList FileList); + virtual void OnInsertFiles(QStringList FileList); + +protected: + QString m_ArchivePath; + QString m_Password; + quint64 m_PartSize; + + QString m_WinRarPath; + QString m_CommentPath; +}; diff --git a/SandboxiePlus/MiscHelpers/Archive/ArchiveUpdater.cpp b/SandboxiePlus/MiscHelpers/Archive/ArchiveUpdater.cpp new file mode 100644 index 00000000..a1f3810f --- /dev/null +++ b/SandboxiePlus/MiscHelpers/Archive/ArchiveUpdater.cpp @@ -0,0 +1,106 @@ +#include "stdafx.h" +#include "ArchiveUpdater.h" +#include "Archive.h" + +#ifdef USE_7Z + +CArchiveUpdater::CArchiveUpdater(CArchive* pArchive, const QMap& Files) +{ + m_pArchive = pArchive; + m_Files = Files; +} + +CArchiveUpdater::~CArchiveUpdater() +{ + foreach(CArchiveIO* pFile, m_Files) + delete pFile; +} + +STDMETHODIMP CArchiveUpdater::SetTotal(UInt64 size) +{ + m_pArchive->m_Progress.SetTotal(size); + return S_OK; +} + +STDMETHODIMP CArchiveUpdater::SetCompleted(const UInt64 *completeValue) +{ + ASSERT(completeValue); + m_pArchive->m_Progress.SetCompleted(*completeValue); + return S_OK; +} + +STDMETHODIMP CArchiveUpdater::GetUpdateItemInfo(UInt32 index, Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive) +{ + if (newData != NULL) + *newData = true; + if (newProperties != NULL) + *newProperties = true; + if (indexInArchive != NULL) + *indexInArchive = (UInt32)-1; + return S_OK; +} + +STDMETHODIMP CArchiveUpdater::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + NWindows::NCOM::CPropVariant prop; + if (propID == kpidIsAnti) + prop = false; + else + { + Q_ASSERT(index < m_pArchive->m_Files.count()); + int ArcIndex = m_pArchive->m_Files[index].ArcIndex; + switch(propID) + { + case kpidPath: prop = m_pArchive->FileProperty(ArcIndex, "Path").toString().toStdWString().c_str(); break; + case kpidSize: prop = m_pArchive->FileProperty(ArcIndex, "Size").toULongLong(); break; + case kpidAttrib: prop = m_pArchive->FileProperty(ArcIndex, "Attrib").toUInt(); break; + case kpidIsDir: prop = m_pArchive->FileProperty(ArcIndex, "IsDir").toBool(); break; + case kpidCTime: {quint64 date = m_pArchive->FileProperty(ArcIndex, "CTime").toULongLong(); // ToDo + prop = *reinterpret_cast(&date);} break; + case kpidATime: {quint64 date = m_pArchive->FileProperty(ArcIndex, "ATime").toULongLong(); // ToDo + prop = *reinterpret_cast(&date);} break; + case kpidMTime: {quint64 date = m_pArchive->FileProperty(ArcIndex, "MTime").toULongLong(); // ToDo + prop = *reinterpret_cast(&date);} break; + //default: Q_ASSERT(0); // ToDo + } + } + prop.Detach(value); + return S_OK; +} + +STDMETHODIMP CArchiveUpdater::GetStream(UInt32 index, ISequentialInStream **inStream) +{ + *inStream = NULL; + Q_ASSERT(index < m_pArchive->m_Files.count()); + int ArcIndex = m_pArchive->m_Files[index].ArcIndex; + //TRACE(L"Archive Item '%S'", QS2CS(m_pArchive->FileProperty(ArcIndex, "Path").toString())); + CArchiveIO* pFile = m_Files.take(ArcIndex); + if(pFile == NULL) + { + QTemporaryFile* pTemp = new QTemporaryFile; + QMap Files; + Files.insert(ArcIndex, pTemp); + if(!m_pArchive->Extract(&Files,false)) + { + m_pArchive->LogError(QString("Failed to extract old %1 file form source archive").arg(m_pArchive->FileProperty(ArcIndex, "Path").toString())); + TRACE(L"Failed to extract old file form source archive"); + delete pTemp; + return E_ABORT; + } + pFile = new CArchiveIO(pTemp, QIODevice::ReadOnly); + } + if (!pFile->Open(QIODevice::ReadOnly)) + return S_FALSE; + CMyComPtr inStreamLoc = pFile; + *inStream = inStreamLoc.Detach(); + return S_OK; +} + +STDMETHODIMP CArchiveUpdater::CryptoGetTextPassword2(Int32 *passwordIsDefined, BSTR *password) +{ + QString Password = m_pArchive->GetPassword(true); + *passwordIsDefined = Password.isEmpty() ? false : true; + return StringToBstr(Password.toStdWString().c_str(), password); +} + +#endif \ No newline at end of file diff --git a/SandboxiePlus/MiscHelpers/Archive/ArchiveUpdater.h b/SandboxiePlus/MiscHelpers/Archive/ArchiveUpdater.h new file mode 100644 index 00000000..82445127 --- /dev/null +++ b/SandboxiePlus/MiscHelpers/Archive/ArchiveUpdater.h @@ -0,0 +1,38 @@ +#pragma once + +#include "ArchiveHelper.h" + +#ifdef USE_7Z + +class CArchiveUpdater: public IArchiveUpdateCallback2, public ICryptoGetTextPassword2, public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP2(IArchiveUpdateCallback2, ICryptoGetTextPassword2) + + CArchiveUpdater(CArchive* pArchive, const QMap& Files); + ~CArchiveUpdater(); + + // IProgress + STDMETHOD(SetTotal)(UInt64 size); + STDMETHOD(SetCompleted)(const UInt64 *completeValue); + + // IArchiveUpdateCallback2 + STDMETHOD(GetUpdateItemInfo)(UInt32 index, Int32 *newData, Int32 *newProperties, UInt32 *indexInArchive); + STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); + STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream); + STDMETHOD(SetOperationResult)(Int32 operationResult) {return S_OK;} + + // depricated + STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size) {return S_FALSE;} + STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream) {return S_FALSE;} + + // ICryptoGetTextPassword2 + STDMETHOD(CryptoGetTextPassword2)(Int32 *passwordIsDefined, BSTR *password); + +protected: + CArchive* m_pArchive; + + QMap m_Files; +}; + +#endif \ No newline at end of file diff --git a/SandboxiePlus/MiscHelpers/Archive/CachedArchive.cpp b/SandboxiePlus/MiscHelpers/Archive/CachedArchive.cpp new file mode 100644 index 00000000..11fb765a --- /dev/null +++ b/SandboxiePlus/MiscHelpers/Archive/CachedArchive.cpp @@ -0,0 +1,37 @@ +#include "stdafx.h" +#include "CachedArchive.h" + +#ifdef USE_7Z + +CCachedArchive::CCachedArchive(const QString &ArchivePath) + : CArchive(ArchivePath) +{ +} + +bool CCachedArchive::Extract(QMap *FileList, bool bDelete) +{ + QMap Files; + foreach(int ArcIndex, FileList->keys()) + { + if(!m_CacheMap.contains(ArcIndex)) + Files.insert(ArcIndex, new QBuffer(&m_CacheMap[ArcIndex])); + } + + if(!Files.isEmpty()) + { + if(!CArchive::Extract(&Files)) + return false; + } + + foreach(int ArcIndex, FileList->keys()) + { + QIODevice* pIO = FileList->value(ArcIndex); + pIO->open(QIODevice::WriteOnly); + pIO->write(m_CacheMap.value(ArcIndex)); + pIO->close(); + delete pIO; + } + return true; +} + +#endif \ No newline at end of file diff --git a/SandboxiePlus/MiscHelpers/Archive/CachedArchive.h b/SandboxiePlus/MiscHelpers/Archive/CachedArchive.h new file mode 100644 index 00000000..166d30a9 --- /dev/null +++ b/SandboxiePlus/MiscHelpers/Archive/CachedArchive.h @@ -0,0 +1,22 @@ +#pragma once + +#include "../mischelpers_global.h" + +#include "Archive.h" + +#ifdef USE_7Z + +class MISCHELPERS_EXPORT CCachedArchive: public CArchive +{ +public: + CCachedArchive(const QString &ArchivePath); + + bool Update(QMap *FileList, bool bDelete = true) {LogError("Cachen archives can not be updated"); return false;} + bool Extract(QMap *FileList, bool bDelete = true); + +protected: + + QMap m_CacheMap; +}; + +#endif \ No newline at end of file diff --git a/SandboxiePlus/MiscHelpers/Archive/SplitFile.cpp b/SandboxiePlus/MiscHelpers/Archive/SplitFile.cpp new file mode 100644 index 00000000..78ba69f5 --- /dev/null +++ b/SandboxiePlus/MiscHelpers/Archive/SplitFile.cpp @@ -0,0 +1,186 @@ +#include "stdafx.h" +#include "SplitFile.h" + + +CSplitFile::CSplitFile(const QString &name, quint64 size) +{ + m_PartSize = size; + m_FileName = name; + + m_Position = 0; + m_Index = -1; +} + +CSplitFile::~CSplitFile() +{ + QIODevice::close(); +} + +QString CSplitFile::GetPartName(int Index) +{ + QString Ext = QString::number(Index+1); + while(Ext.length() < 3) + Ext.prepend("0"); + return m_FileName + "." + Ext; +} + +bool CSplitFile::open(OpenMode flags) +{ + if(flags & ReadOnly) + { + for(int i = 0;; i++) + { + QString PartName = GetPartName(i); + if(!QFile::exists(PartName)) + break; + + QFile* pFile = new QFile(PartName, this); + pFile->open(flags); + m_FileParts.append(pFile); + } + } + + m_Index = 0; // we are open for business + return QIODevice::open(flags); +} + +void CSplitFile::close() +{ + m_Position = 0; + m_Index = -1; + foreach(QFile* pPart, m_FileParts) + { + pPart->close(); + delete pPart; + } + m_FileParts.clear(); + QIODevice::close(); +} + +qint64 CSplitFile::size() const +{ + quint64 uSize = 0; + foreach(QFile* pPart, m_FileParts) + uSize += pPart->size(); + return uSize; +} + +qint64 CSplitFile::pos() const +{ + return m_Position; +} + +bool CSplitFile::seek(qint64 offset) +{ + if(m_Index == -1) + return false; + + qint64 iToGo = offset - m_Position; + int i = m_Index; + + while(iToGo) + { + if(iToGo > 0) + { + qint64 tmp = m_FileParts[i]->pos(); + if(tmp + iToGo < (qint64)m_PartSize) + { + m_FileParts[i]->seek(tmp + iToGo); + //iToGo = 0; + break; + } + else + { + if(++i == m_FileParts.count()) + { + QFile* pFile = new QFile(GetPartName(m_Index), this); + pFile->open(openMode()); + m_FileParts.append(pFile); + } + iToGo -= tmp; + m_FileParts[i]->seek(0); + } + } + else if(iToGo < 0) + { + qint64 tmp = m_FileParts[i]->pos(); + if(tmp -iToGo >= 0) + { + m_FileParts[i]->seek(tmp + iToGo); + //iToGo = 0; + break; + } + else + { + if(--i == -1) + return false; + iToGo += tmp; + m_FileParts[i]->seek(m_FileParts[i]->size()-1); + } + } + } + + m_Index = i; + m_Position = offset; + return true; +} + +qint64 CSplitFile::readData(char *data, qint64 maxlen) +{ + if(m_Index == -1) + return -1; + + quint64 read = 0; + while(maxlen - read) + { + if(m_Index >= m_FileParts.count()) + break; + + quint64 uToGo = maxlen - read; + quint64 uAvail = m_FileParts[m_Index]->size() - m_FileParts[m_Index]->pos(); + if(uToGo > uAvail) + uToGo = uAvail; + + quint64 Tmp = m_FileParts[m_Index]->read(data + read, uToGo); + if(Tmp == -1) + return -1; + read += Tmp; + m_Position += Tmp; + + if(m_FileParts[m_Index]->pos() >= m_FileParts[m_Index]->size()) + m_Index++; + } + return read; +} + +qint64 CSplitFile::writeData(const char *data, qint64 len) +{ + if(m_Index == -1) + return -1; + + quint64 writen = 0; + while(len - writen) + { + if(m_Index >= m_FileParts.count()) + { + QFile* pFile = new QFile(GetPartName(m_Index), this); + pFile->open(openMode()); + m_FileParts.append(pFile); + } + + quint64 uToGo = len - writen; + quint64 uAvail = m_PartSize - m_FileParts[m_Index]->pos(); + if(uToGo > uAvail) + uToGo = uAvail; + + quint64 Tmp = m_FileParts[m_Index]->write(data + writen, uToGo); + if(Tmp == -1) + return -1; + writen += Tmp; + m_Position += Tmp; + + if(m_FileParts[m_Index]->pos() >= (qint64)m_PartSize) + m_Index++; + } + return writen; +} \ No newline at end of file diff --git a/SandboxiePlus/MiscHelpers/Archive/SplitFile.h b/SandboxiePlus/MiscHelpers/Archive/SplitFile.h new file mode 100644 index 00000000..9c814fb4 --- /dev/null +++ b/SandboxiePlus/MiscHelpers/Archive/SplitFile.h @@ -0,0 +1,32 @@ +#pragma once + +#include "../mischelpers_global.h" + +class MISCHELPERS_EXPORT CSplitFile : public QIODevice +{ + Q_OBJECT +public: + CSplitFile(const QString &name, quint64 size = -1); + ~CSplitFile(); + + virtual bool open(OpenMode flags); + virtual void close(); + virtual qint64 size() const; + virtual qint64 pos() const; + virtual bool seek(qint64 offset); + virtual bool atEnd() const {return pos() >= size();} + +protected: + virtual qint64 readData(char *data, qint64 maxlen); + virtual qint64 writeData(const char *data, qint64 len); + + QString GetPartName(int Index); + + quint64 m_PartSize; + QString m_FileName; + + QVector m_FileParts; + + quint64 m_Position; + int m_Index; +}; diff --git a/SandboxiePlus/MiscHelpers/Common/Finder.cpp b/SandboxiePlus/MiscHelpers/Common/Finder.cpp index e9e45292..aa8fa7bb 100644 --- a/SandboxiePlus/MiscHelpers/Common/Finder.cpp +++ b/SandboxiePlus/MiscHelpers/Common/Finder.cpp @@ -144,7 +144,7 @@ QRegularExpression CFinder::GetRegExp() const if(m_pRegExp->isChecked()) Exp = m_pSearch->text(); else - Exp = QRegularExpression::wildcardToRegularExpression("*" + m_pSearch->text() + "*"); + Exp = ".*" + QRegularExpression::escape(m_pSearch->text()) + ".*"; return QRegularExpression(Exp, m_pCaseSensitive->isChecked() ? QRegularExpression::NoPatternOption : QRegularExpression::CaseInsensitiveOption); } diff --git a/SandboxiePlus/MiscHelpers/Common/MT/ThreadLock.cpp b/SandboxiePlus/MiscHelpers/Common/MT/ThreadLock.cpp new file mode 100644 index 00000000..82c1bc99 --- /dev/null +++ b/SandboxiePlus/MiscHelpers/Common/MT/ThreadLock.cpp @@ -0,0 +1,37 @@ +#include "stdafx.h" +#include "ThreadLock.h" + + +/********************************************************************************************** +* CThreadLock +*/ + +CThreadLock::CThreadLock() +{ + m_Released = false; +} + +void CThreadLock::Reset() +{ + m_Mutex.lock(); + m_Released = false; + m_Mutex.unlock(); +} + +bool CThreadLock::Lock(unsigned long time) +{ + bool bRet = true; + m_Mutex.lock(); + if(m_Released == false) + bRet = m_Wait.wait(&m_Mutex, time); + m_Mutex.unlock(); + return bRet; +} + +void CThreadLock::Release() +{ + m_Mutex.lock(); + m_Released = true; + m_Wait.wakeAll(); + m_Mutex.unlock(); +} diff --git a/SandboxiePlus/MiscHelpers/Common/MT/ThreadLock.h b/SandboxiePlus/MiscHelpers/Common/MT/ThreadLock.h new file mode 100644 index 00000000..0fbb08d3 --- /dev/null +++ b/SandboxiePlus/MiscHelpers/Common/MT/ThreadLock.h @@ -0,0 +1,28 @@ +#pragma once + +#include "../../mischelpers_global.h" + +#include +#include + +/********************************************************************************************** +* CThreadLock +* This class allows to wait for events form a differet thread. +* When Lock returns successfuly it is guaranted that the other thread have issued a release. +* This works undependant of the real order Lock and Release ware calles +*/ + +class MISCHELPERS_EXPORT CThreadLock +{ +public: + CThreadLock(); + + void Reset(); + bool Lock(unsigned long time = ULONG_MAX); + void Release(); + +protected: + QMutex m_Mutex; + QWaitCondition m_Wait; + bool m_Released; +}; diff --git a/SandboxiePlus/MiscHelpers/Common/ProgressDialog.h b/SandboxiePlus/MiscHelpers/Common/ProgressDialog.h index 0136fabd..234441df 100644 --- a/SandboxiePlus/MiscHelpers/Common/ProgressDialog.h +++ b/SandboxiePlus/MiscHelpers/Common/ProgressDialog.h @@ -20,7 +20,9 @@ public: m_pMessageLabel = new QLabel(Prompt); m_pMessageLabel->setMinimumWidth(300); + //m_pMessageLabel->setMinimumHeight(40); m_pMessageLabel->setWordWrap(true); + //m_pMessageLabel->setAlignment(Qt::AlignTop); m_pMainLayout->addWidget(m_pMessageLabel, 0, 0, 1, 1); m_pProgressBar = new QProgressBar(); diff --git a/SandboxiePlus/MiscHelpers/MiscHelpers.pri b/SandboxiePlus/MiscHelpers/MiscHelpers.pri index 0d9ed617..67a780c0 100644 --- a/SandboxiePlus/MiscHelpers/MiscHelpers.pri +++ b/SandboxiePlus/MiscHelpers/MiscHelpers.pri @@ -34,7 +34,19 @@ HEADERS += ./MiscHelpers.h \ ./Common/TreeWidgetEx.h \ ./Common/CheckList.h \ ./Common/NeonEffect.h \ - ./Common/NetworkAccessManager.h + ./Common/NetworkAccessManager.h \ + ./Common/MT/ThreadLock.h \ + ./Archive/Archive.h \ + ./Archive/ArchiveFS.h \ + ./Archive/ArchiveExtractor.h \ + ./Archive/ArchiveHelper.h \ + ./Archive/ArchiveInterface.h \ + ./Archive/ArchiveIO.h \ + ./Archive/ArchiveOpener.h \ + ./Archive/ArchiveThread.h \ + ./Archive/ArchiveUpdater.h \ + ./Archive/CachedArchive.h \ + ./Archive/SplitFile.h SOURCES += ./MiscHelpers.cpp \ ./stdafx.cpp \ @@ -58,4 +70,16 @@ SOURCES += ./MiscHelpers.cpp \ ./Common/SplitTreeView.cpp \ ./Common/TabPanel.cpp \ ./Common/TreeItemModel.cpp \ - ./Common/Xml.cpp + ./Common/Xml.cpp \ + ./Common/MT/ThreadLock.cpp \ + ./Archive/Archive.cpp \ + ./Archive/ArchiveFS.cpp \ + ./Archive/ArchiveExtractor.cpp \ + ./Archive/ArchiveHelper.cpp \ + ./Archive/ArchiveInterface.cpp \ + ./Archive/ArchiveOpener.cpp \ + ./Archive/ArchiveThread.cpp \ + ./Archive/ArchiveUpdater.cpp \ + ./Archive/CachedArchive.cpp \ + ./Archive/SplitFile.cpp + diff --git a/SandboxiePlus/MiscHelpers/MiscHelpers.vcxproj b/SandboxiePlus/MiscHelpers/MiscHelpers.vcxproj index 48391ce4..f25e4095 100644 --- a/SandboxiePlus/MiscHelpers/MiscHelpers.vcxproj +++ b/SandboxiePlus/MiscHelpers/MiscHelpers.vcxproj @@ -189,6 +189,16 @@ + + + + + + + + + + @@ -198,6 +208,7 @@ + @@ -222,6 +233,17 @@ + + + + + + + + + + + @@ -244,6 +266,7 @@ + diff --git a/SandboxiePlus/MiscHelpers/MiscHelpers.vcxproj.filters b/SandboxiePlus/MiscHelpers/MiscHelpers.vcxproj.filters index 6813dba1..dcd8fa0b 100644 --- a/SandboxiePlus/MiscHelpers/MiscHelpers.vcxproj.filters +++ b/SandboxiePlus/MiscHelpers/MiscHelpers.vcxproj.filters @@ -22,6 +22,12 @@ {964acff8-ecee-4dfc-939d-e2406a533100} + + {1e331c49-0544-4a02-83e5-e47774ab5fac} + + + {55ef64ac-4671-4600-8e4a-ca56d181c6ec} + @@ -93,6 +99,39 @@ Common + + Archive + + + Archive + + + Archive + + + Archive + + + Archive + + + Archive + + + Archive + + + Archive + + + Archive + + + Common\MT + + + Archive + @@ -128,6 +167,36 @@ Common + + Archive + + + Archive + + + Archive + + + Archive + + + Archive + + + Archive + + + Archive + + + Archive + + + Common\MT + + + Archive + @@ -195,6 +264,12 @@ Common + + Archive + + + Archive + Common diff --git a/SandboxiePlus/SandMan/SandMan.cpp b/SandboxiePlus/SandMan/SandMan.cpp index 3655ea14..0fe8062b 100644 --- a/SandboxiePlus/SandMan/SandMan.cpp +++ b/SandboxiePlus/SandMan/SandMan.cpp @@ -26,10 +26,13 @@ #include "../MiscHelpers/Common/OtherFunctions.h" #include "../MiscHelpers/Common/Common.h" #include "Windows/SupportDialog.h" +#include "../MiscHelpers/Archive/Archive.h" +#include "../MiscHelpers/Archive/ArchiveFS.h" #include "Views/FileView.h" #include "OnlineUpdater.h" #include "../MiscHelpers/Common/NeonEffect.h" #include +#include CSbiePlusAPI* theAPI = NULL; @@ -110,6 +113,10 @@ CSandMan::CSandMan(QWidget *parent) QApplication::instance()->installNativeEventFilter(new CNativeEventFilter); #endif + CArchive::Init(); + + m_pTranslations = new C7zFileEngineHandler(QApplication::applicationDirPath() + "/translations.7z", "lang", this); + theGUI = this; m_DarkTheme = false; @@ -447,6 +454,7 @@ void CSandMan::CreateMenus(bool bAdvanced) m_pMenuFile = m_pMenuBar->addMenu(tr("&Sandbox")); m_pNewBox = m_pMenuFile->addAction(CSandMan::GetIcon("NewBox"), tr("Create New Box"), this, SLOT(OnSandBoxAction())); m_pNewGroup = m_pMenuFile->addAction(CSandMan::GetIcon("Group"), tr("Create Box Group"), this, SLOT(OnSandBoxAction())); + m_pImportBox = m_pMenuFile->addAction(CSandMan::GetIcon("UnPackBox"), tr("Import Box"), this, SLOT(OnSandBoxAction())); m_pMenuFile->addSeparator(); m_pEmptyAll = m_pMenuFile->addAction(CSandMan::GetIcon("EmptyAll"), tr("Terminate All Processes"), this, SLOT(OnEmptyAll())); m_pDisableForce = m_pMenuFile->addAction(tr("Pause Forcing Programs"), this, SLOT(OnDisableForce())); @@ -645,6 +653,7 @@ void CSandMan::CreateOldMenus() m_pSandbox->addSeparator(); m_pNewBox = m_pSandbox->addAction(CSandMan::GetIcon("NewBox"), tr("Create New Sandbox"), this, SLOT(OnSandBoxAction())); m_pNewGroup = m_pSandbox->addAction(CSandMan::GetIcon("Group"), tr("Create New Group"), this, SLOT(OnSandBoxAction())); + m_pImportBox = m_pSandbox->addAction(CSandMan::GetIcon("UnPackBox"), tr("Import Sandbox"), this, SLOT(OnSandBoxAction())); QAction* m_pSetContainer = m_pSandbox->addAction(CSandMan::GetIcon("Advanced"), tr("Set Container Folder"), this, SLOT(OnSettingsAction())); m_pSetContainer->setData(CSettingsWindow::eAdvanced); @@ -2167,10 +2176,48 @@ void CSandMan::OnSandBoxAction() { QAction* pAction = qobject_cast(sender()); - if(pAction == m_pNewBox) + if (pAction == m_pNewBox) GetBoxView()->AddNewBox(); - else if(pAction == m_pNewGroup) + else if (pAction == m_pNewGroup) GetBoxView()->AddNewGroup(); + else if (pAction == m_pImportBox) + { + QString Value = QFileDialog::getOpenFileName(this, tr("Select file name"), "", tr("7-zip Archive (*.7z)")); + if (Value.isEmpty()) + return; + + StrPair PathName = Split2(Value, "/", true); + StrPair NameEx = Split2(PathName.second, ".", true); + QString Name = NameEx.first; + + CSandBoxPtr pBox; + for (;;) { + pBox = theAPI->GetBoxByName(Name); + if (pBox.isNull()) + break; + Name = QInputDialog::getText(this, "Sandboxie-Plus", tr("This Name is already in use, please select an alternative box name"), QLineEdit::Normal, Name); + if (Name.isEmpty()) + return; + } + + SB_PROGRESS Status = theAPI->CreateBox(Name); + if (!Status.IsError()) { + pBox = theAPI->GetBoxByName(Name); + if (pBox) { + auto pBoxEx = pBox.objectCast(); + Status = pBoxEx->ImportBox(Value); + } + } + if (Status.GetStatus() == OP_ASYNC) { + Status = theGUI->AddAsyncOp(Status.GetValue(), true, tr("Importing: %1").arg(Value)); + if (Status.IsError()) { + theGUI->DeleteBoxContent(pBox, CSandMan::eForDelete); + pBox->RemoveBox(); + } + } + else + CSandMan::CheckResults(QList() << Status); + } } void CSandMan::OnEmptyAll() @@ -2832,6 +2879,13 @@ QString CSandMan::FormatError(const SB_STATUS& Error) case SB_NameExists: Message = tr("A sandbox with that name already exists"); break; case SB_PasswordBad: Message = tr("The config password must not be longer than 64 characters"); break; case SB_Canceled: Message = tr("The operation was canceled by the user"); break; + + case SBX_7zNotReady: Message = tr("Import/Export not available, 7z.dll could not be loaded"); break; + case SBX_7zCreateFailed: Message = tr("Failed to Create Box Archive"); break; + case SBX_7zOpenFailed: Message = tr("Failed to open the 7z archive"); break; + case SBX_7zExtractFailed: Message = tr("Failed to Unpack Box Archive"); break; + case SBX_NotBoxArchive: Message = tr("The sellected 7z file is NOT a Box Archive"); break; + default: return tr("Unknown Error Status: 0x%1").arg((quint32)Error.GetStatus(), 8, 16, QChar('0')); } @@ -3033,7 +3087,11 @@ void CSandMan::LoadLanguage(const QString& Lang, const QString& Module, int Inde QString LangAux = Lang; // Short version as fallback LangAux.truncate(LangAux.lastIndexOf('_')); - QString LangDir = QApplication::applicationDirPath() + "/translations/"; + QString LangDir; + if (m_pTranslations->IsOpen()) + LangDir = m_pTranslations->Prefix() + "/"; + else + LangDir = QApplication::applicationDirPath() + "/translations/"; QString LangPath = LangDir + Module + "_"; bool bAux = false; diff --git a/SandboxiePlus/SandMan/SandMan.h b/SandboxiePlus/SandMan/SandMan.h index c2e205fa..44467d45 100644 --- a/SandboxiePlus/SandMan/SandMan.h +++ b/SandboxiePlus/SandMan/SandMan.h @@ -282,6 +282,7 @@ private: QMenu* m_pMenuFile; QAction* m_pNewBox; QAction* m_pNewGroup; + QAction* m_pImportBox; QAction* m_pEmptyAll; QAction* m_pWndFinder; QAction* m_pDisableForce; @@ -381,6 +382,7 @@ public: quint32 m_LanguageId; bool m_DarkTheme; bool m_FusionTheme; + class C7zFileEngineHandler* m_pTranslations; }; diff --git a/SandboxiePlus/SandMan/SbiePlusAPI.cpp b/SandboxiePlus/SandMan/SbiePlusAPI.cpp index 9b2fa308..4625ab4d 100644 --- a/SandboxiePlus/SandMan/SbiePlusAPI.cpp +++ b/SandboxiePlus/SandMan/SbiePlusAPI.cpp @@ -8,6 +8,8 @@ #include "BoxMonitor.h" #include "..\MiscHelpers\Common\OtherFunctions.h" #include "../QSbieAPI/SbieUtils.h" +#include "../MiscHelpers/Archive/Archive.h" +#include CSbiePlusAPI::CSbiePlusAPI(QObject* parent) : CSbieAPI(parent) { @@ -147,6 +149,160 @@ CSandBoxPlus::~CSandBoxPlus() { } +class QFileX : public QFile { +public: + QFileX(const QString& path, const CSbieProgressPtr& pProgress, CArchive* pArchive) : QFile(path) + { + m_pProgress = pProgress; + m_pArchive = pArchive; + } + + bool open(OpenMode flags) override + { + if (m_pProgress->IsCanceled()) + return false; + m_pProgress->ShowMessage(Split2(fileName(), "/", true).second); + m_pProgress->SetProgress((int)(m_pArchive->GetProgress() * 100.0)); + return QFile::open(flags); + } + +protected: + CSbieProgressPtr m_pProgress; + CArchive* m_pArchive; +}; + +void CSandBoxPlus::ExportBoxAsync(const CSbieProgressPtr& pProgress, const QString& ExportPath, const QString& RootPath, const QString& Section) +{ + //CArchive Archive(ExportPath + ".tmp"); + CArchive Archive(ExportPath); + + QMap Files; + + //QTemporaryFile* pConfigFile = new QTemporaryFile; + //pConfigFile->open(); + //pConfigFile->write(Section.toUtf8()); + //pConfigFile->close(); + // + //int ArcIndex = Archive.AddFile("BoxConfig.ini"); + //Files.insert(ArcIndex, pConfigFile); + + QFile File(RootPath + "\\" + "BoxConfig.ini"); + if (File.open(QFile::WriteOnly)) { + File.write(Section.toUtf8()); + File.close(); + } + + QStringList FileList = ListDir(RootPath + "\\"); + foreach(const QString& File, FileList) + { + StrPair RootName = Split2(File, "\\", true); + if(RootName.second.isEmpty()) + { + RootName.second = RootName.first; + RootName.first = ""; + } + int ArcIndex = Archive.AddFile(RootName.second); + if(ArcIndex != -1) + { + QString FileName = (RootName.first.isEmpty() ? RootPath + "\\" : RootName.first) + RootName.second; + Files.insert(ArcIndex, new QFileX(FileName, pProgress, &Archive)); + } + //else + // this file is already present in the archive, this should not happen !!! + } + + SB_STATUS Status = SB_OK; + if (!Archive.Update(&Files)) + Status = SB_ERR((ESbieMsgCodes)SBX_7zCreateFailed); + + //if(!Status.IsError() && !pProgress->IsCanceled()) + // QFile::rename(ExportPath + ".tmp", ExportPath); + //else + // QFile::remove(ExportPath + ".tmp"); + + File.remove(); + + pProgress->Finish(Status); +} + +SB_PROGRESS CSandBoxPlus::ExportBox(const QString& FileName) +{ + if (!CArchive::IsInit()) + return SB_ERR((ESbieMsgCodes)SBX_7zNotReady); + + if (theAPI->HasProcesses(m_Name)) + return SB_ERR(SB_SnapIsRunning); // todo + + if (!IsInitialized()) + return SB_ERR(SB_SnapIsEmpty); // todo + + QString Section = theAPI->SbieIniGetEx(m_Name, ""); + + CSbieProgressPtr pProgress = CSbieProgressPtr(new CSbieProgress()); + QtConcurrent::run(CSandBoxPlus::ExportBoxAsync, pProgress, FileName, m_FilePath, Section); + return SB_PROGRESS(OP_ASYNC, pProgress); +} + +void CSandBoxPlus::ImportBoxAsync(const CSbieProgressPtr& pProgress, const QString& ImportPath, const QString& RootPath, const QString& BoxName) +{ + CArchive Archive(ImportPath); + + if (Archive.Open() != 1) { + pProgress->Finish(SB_ERR((ESbieMsgCodes)SBX_7zOpenFailed)); + return; + } + + bool IsBoxArchive = false; + + QMap Files; + + for (int i = 0; i < Archive.FileCount(); i++) { + int ArcIndex = Archive.FindByIndex(i); + if(Archive.FileProperty(ArcIndex, "IsDir").toBool()) + continue; + QString File = Archive.FileProperty(ArcIndex, "Path").toString(); + if (File == "BoxConfig.ini") + IsBoxArchive = true; + Files.insert(ArcIndex, new QFileX(CArchive::PrepareExtraction(File, RootPath + "\\"), pProgress, &Archive)); + } + + if(!IsBoxArchive) { + pProgress->Finish(SB_ERR((ESbieMsgCodes)SBX_NotBoxArchive)); + return; + } + + SB_STATUS Status = SB_OK; + if (!Archive.Extract(&Files)) + Status = SB_ERR((ESbieMsgCodes)SBX_7zExtractFailed); + + if (!Status.IsError() && !pProgress->IsCanceled()) + { + QFile File(RootPath + "\\" + "BoxConfig.ini"); + if (File.open(QFile::ReadOnly)) { + + QMetaObject::invokeMethod(theAPI, "SbieIniSetSection", Qt::BlockingQueuedConnection, // run this in the main thread + Q_ARG(QString, BoxName), + Q_ARG(QString, QString::fromUtf8(File.readAll())) + ); + + File.close(); + } + File.remove(); + } + + pProgress->Finish(Status); +} + +SB_PROGRESS CSandBoxPlus::ImportBox(const QString& FileName) +{ + if (!CArchive::IsInit()) + return SB_ERR((ESbieMsgCodes)SBX_7zNotReady); + + CSbieProgressPtr pProgress = CSbieProgressPtr(new CSbieProgress()); + QtConcurrent::run(CSandBoxPlus::ImportBoxAsync, pProgress, FileName, m_FilePath, m_Name); + return SB_PROGRESS(OP_ASYNC, pProgress); +} + void CSandBoxPlus::UpdateDetails() { //m_bLogApiFound = GetTextList("OpenPipePath", false).contains("\\Device\\NamedPipe\\LogAPI"); diff --git a/SandboxiePlus/SandMan/SbiePlusAPI.h b/SandboxiePlus/SandMan/SbiePlusAPI.h index 0c9e972c..39ac9871 100644 --- a/SandboxiePlus/SandMan/SbiePlusAPI.h +++ b/SandboxiePlus/SandMan/SbiePlusAPI.h @@ -3,6 +3,15 @@ #include "../QSbieAPI/SbieAPI.h" #include "BoxJob.h" +enum ESbieExMsgCodes +{ + SBX_FirstError = SB_LastError, + SBX_7zNotReady, + SBX_7zCreateFailed, + SBX_7zOpenFailed, + SBX_7zExtractFailed, + SBX_NotBoxArchive +}; class CSbiePlusAPI : public CSbieAPI { @@ -27,6 +36,7 @@ public: private slots: virtual void OnStartFinished(); + virtual void SbieIniSetSection(const QString& Section, const QString& Value) { SbieIniSet(Section, "", Value); } protected: friend class CSandBoxPlus; @@ -56,6 +66,9 @@ public: CSandBoxPlus(const QString& BoxName, class CSbieAPI* pAPI); virtual ~CSandBoxPlus(); + SB_PROGRESS ExportBox(const QString& FileName); + SB_PROGRESS ImportBox(const QString& FileName); + virtual void UpdateDetails(); virtual void ScanStartMenu(); @@ -167,6 +180,9 @@ protected: void AddJobToQueue(CBoxJob* pJob); void StartNextJob(); + static void ExportBoxAsync(const CSbieProgressPtr& pProgress, const QString& ExportPath, const QString& RootPath, const QString& Section); + static void ImportBoxAsync(const CSbieProgressPtr& pProgress, const QString& ImportPath, const QString& RootPath, const QString& BoxName); + QList> m_JobQueue; bool m_bLogApiFound; diff --git a/SandboxiePlus/SandMan/Views/SbieView.cpp b/SandboxiePlus/SandMan/Views/SbieView.cpp index c90d4f57..4eca1187 100644 --- a/SandboxiePlus/SandMan/Views/SbieView.cpp +++ b/SandboxiePlus/SandMan/Views/SbieView.cpp @@ -185,10 +185,14 @@ void CSbieView::CreateMenu() m_pMenuContent->addSeparator(); m_pMenuExplore = m_pMenuContent->addAction(CSandMan::GetIcon("Explore"), tr("Explore Content"), this, SLOT(OnSandBoxAction())); m_pMenuRegEdit = m_pMenuContent->addAction(CSandMan::GetIcon("RegEdit"), tr("Open Registry"), this, SLOT(OnSandBoxAction())); + m_pMenuSnapshots = m_pMenuBox->addAction(CSandMan::GetIcon("Snapshots"), tr("Snapshots Manager"), this, SLOT(OnSandBoxAction())); m_pMenuRecover = m_pMenuBox->addAction(CSandMan::GetIcon("Recover"), tr("Recover Files"), this, SLOT(OnSandBoxAction())); m_pMenuCleanUp = m_pMenuBox->addAction(CSandMan::GetIcon("Erase"), tr("Delete Content"), this, SLOT(OnSandBoxAction())); m_pMenuBox->addSeparator(); m_pMenuOptions = m_pMenuBox->addAction(CSandMan::GetIcon("Options"), tr("Sandbox Options"), this, SLOT(OnSandBoxAction())); + QFont f = m_pMenuOptions->font(); + f.setBold(true); + m_pMenuOptions->setFont(f); m_pMenuPresets = m_pMenuBox->addMenu(CSandMan::GetIcon("Presets"), tr("Sandbox Presets")); m_pMenuPresetsAdmin = new QActionGroup(m_pMenuPresets); @@ -212,9 +216,8 @@ void CSbieView::CreateMenu() m_pMenuPresetsRecovery->setCheckable(true); m_pMenuTools = m_pMenuBox->addMenu(CSandMan::GetIcon("Maintenance"), tr("Sandbox Tools")); - m_pMenuSnapshots = m_pMenuTools->addAction(CSandMan::GetIcon("Snapshots"), tr("Snapshots Manager"), this, SLOT(OnSandBoxAction())); - m_pMenuTools->addSeparator(); m_pMenuDuplicate = m_pMenuTools->addAction(CSandMan::GetIcon("Duplicate"), tr("Duplicate Box Config"), this, SLOT(OnSandBoxAction())); + m_pMenuExport = m_pMenuTools->addAction(CSandMan::GetIcon("PackBox"), tr("Export Box"), this, SLOT(OnSandBoxAction())); m_pMenuRename = m_pMenuBox->addAction(CSandMan::GetIcon("Rename"), tr("Rename Sandbox"), this, SLOT(OnSandBoxAction())); m_pMenuMoveTo = m_pMenuBox->addMenu(CSandMan::GetIcon("Group"), tr("Move Sandbox")); @@ -303,6 +306,7 @@ void CSbieView::CreateOldMenu() m_pMenuTools->addSeparator(); m_pMenuDuplicate = m_pMenuTools->addAction(CSandMan::GetIcon("Duplicate"), tr("Duplicate Sandbox Config"), this, SLOT(OnSandBoxAction())); + m_pMenuExport = m_pMenuTools->addAction(CSandMan::GetIcon("PackBox"), tr("Export Sandbox"), this, SLOT(OnSandBoxAction())); m_pMenuTools->addSeparator(); m_pMenuRefresh = m_pMenuTools->addAction(CSandMan::GetIcon("Refresh"), tr("Refresh Info"), this, SLOT(OnSandBoxAction())); @@ -1226,6 +1230,20 @@ void CSbieView::OnSandBoxAction(QAction* Action, const QList& SandB Results.append(Status); } + else if (Action == m_pMenuExport) + { + QString Value = QFileDialog::getSaveFileName(this, tr("Select file name"), SandBoxes.first()->GetName() + ".7z", tr("7-zip Archive (*.7z)")); + if (Value.isEmpty()) + return; + + CSandBoxPtr pBox = SandBoxes.first(); + auto pBoxEx = pBox.objectCast(); + SB_PROGRESS Status = pBoxEx->ExportBox(Value); + if (Status.GetStatus() == OP_ASYNC) + theGUI->AddAsyncOp(Status.GetValue(), false, tr("Exporting: %1").arg(Value)); + else + Results.append(Status); + } else if (Action == m_pMenuRename) { QString OldValue = SandBoxes.first()->GetName().replace("_", " "); diff --git a/SandboxiePlus/SandMan/Views/SbieView.h b/SandboxiePlus/SandMan/Views/SbieView.h index 0f713126..021061b2 100644 --- a/SandboxiePlus/SandMan/Views/SbieView.h +++ b/SandboxiePlus/SandMan/Views/SbieView.h @@ -158,6 +158,7 @@ private: QAction* m_pMenuRemove; QMenu* m_pMenuTools; QAction* m_pMenuDuplicate; + QAction* m_pMenuExport; QAction* m_pMenuMoveUp; //QAction* m_pMenuMoveBy; QAction* m_pMenuMoveDown;