1.6.0
This commit is contained in:
parent
c09dec5f61
commit
6e496381d8
15
CHANGELOG.md
15
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
|
||||
|
|
|
@ -0,0 +1,254 @@
|
|||
/* Types.h -- Basic types
|
||||
2010-10-09 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_TYPES_H
|
||||
#define __7Z_TYPES_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -0,0 +1,20 @@
|
|||
// Common/Defs.h
|
||||
|
||||
#ifndef __COMMON_DEFS_H
|
||||
#define __COMMON_DEFS_H
|
||||
|
||||
template <class T> inline T MyMin(T a, T b)
|
||||
{ return a < b ? a : b; }
|
||||
template <class T> inline T MyMax(T a, T b)
|
||||
{ return a > b ? a : b; }
|
||||
|
||||
template <class T> 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
|
|
@ -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 T>
|
||||
class CMyComPtr
|
||||
{
|
||||
T* _p;
|
||||
public:
|
||||
// typedef T _PtrClass;
|
||||
CMyComPtr() { _p = NULL;}
|
||||
CMyComPtr(T* p) {if ((_p = p) != NULL) p->AddRef(); }
|
||||
CMyComPtr(const CMyComPtr<T>& 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<T>& 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 <class Q>
|
||||
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
|
|
@ -0,0 +1,22 @@
|
|||
// Common/MyInitGuid.h
|
||||
|
||||
#ifndef __COMMON_MY_INITGUID_H
|
||||
#define __COMMON_MY_INITGUID_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef UNDER_CE
|
||||
#include <basetyps.h>
|
||||
#endif
|
||||
#include <initguid.h>
|
||||
#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
|
|
@ -0,0 +1,13 @@
|
|||
// MyUnknown.h
|
||||
|
||||
#ifndef __MY_UNKNOWN_H
|
||||
#define __MY_UNKNOWN_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <basetyps.h>
|
||||
#include <unknwn.h>
|
||||
#else
|
||||
#include "MyWindows.h"
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,109 @@
|
|||
// MyWindows.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#include "MyWindows.h"
|
||||
#include "Types.h"
|
||||
#include <malloc.h>
|
||||
|
||||
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
|
|
@ -0,0 +1,204 @@
|
|||
// MyWindows.h
|
||||
|
||||
#ifndef __MYWINDOWS_H
|
||||
#define __MYWINDOWS_H
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#else
|
||||
|
||||
#include <stddef.h> // for wchar_t
|
||||
#include <string.h>
|
||||
|
||||
#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
|
|
@ -0,0 +1,116 @@
|
|||
// NewHandler.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
*/
|
|
@ -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
|
|
@ -0,0 +1,11 @@
|
|||
// Common/Types.h
|
||||
|
||||
#ifndef __COMMON_TYPES_H
|
||||
#define __COMMON_TYPES_H
|
||||
|
||||
#include "../../C/Types.h"
|
||||
|
||||
typedef int HRes;
|
||||
|
||||
#endif
|
||||
|
|
@ -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
|
|
@ -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<PROPVARIANT *>(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;
|
||||
}
|
||||
}
|
||||
|
||||
}}
|
|
@ -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
|
|
@ -0,0 +1,9 @@
|
|||
// StdAfx.h
|
||||
|
||||
#ifndef __STDAFX_H
|
||||
#define __STDAFX_H
|
||||
|
||||
#include "../Common/MyWindows.h"
|
||||
#include "../Common/NewHandler.h"
|
||||
|
||||
#endif
|
|
@ -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<IInArchive> &InArchive) {In = InArchive;}
|
||||
~SArchive() {In->Close();}
|
||||
CMyComPtr<IInArchive> 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<IInArchive> 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<IArchiveOpenCallback> 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<qint64*>(&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<int, QIODevice*> 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<int, QIODevice*> *FileList, bool bDelete)
|
||||
{
|
||||
if(!m_Archive)
|
||||
{
|
||||
LogError("archive is not open");
|
||||
return false;
|
||||
}
|
||||
|
||||
QMap<int, CArchiveIO*> Files;
|
||||
foreach(int ArcIndex, FileList->keys())
|
||||
{
|
||||
FileProperty(ArcIndex, "Error", QVariant());
|
||||
Files.insert(ArcIndex, new CArchiveIO(FileList->value(ArcIndex), QIODevice::NotOpen, bDelete));
|
||||
}
|
||||
|
||||
CMyComPtr<IArchiveExtractCallback> 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<int, QIODevice*> *FileList, bool bDelete, int Level)
|
||||
{
|
||||
if(!theArc.IsOperational())
|
||||
{
|
||||
LogError("Couldnt open interface");
|
||||
return false;
|
||||
}
|
||||
|
||||
SArcInfo Info = GetArcInfo(m_ArchivePath);
|
||||
|
||||
CMyComPtr<IOutArchive> OutArchive;
|
||||
if(!theArc.CreateOutArchive(Info.FormatIndex, OutArchive) || !OutArchive)
|
||||
{
|
||||
LogError("Archive can not be updated");
|
||||
return false;
|
||||
}
|
||||
|
||||
CMyComPtr<ISetProperties> 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<int, CArchiveIO*> 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<IArchiveUpdateCallback2> 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;
|
||||
}
|
|
@ -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<int, QIODevice*> *FileList, bool bDelete = true);
|
||||
bool Close();
|
||||
|
||||
bool Update(QMap<int, QIODevice*> *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<SFile> 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;
|
|
@ -0,0 +1,103 @@
|
|||
#include "stdafx.h"
|
||||
#include "ArchiveExtractor.h"
|
||||
#include "Archive.h"
|
||||
|
||||
#ifdef USE_7Z
|
||||
|
||||
CArchiveExtractor::CArchiveExtractor(CArchive* pArchive, const QMap<int,CArchiveIO*>& 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<IOutStream> 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
|
|
@ -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<int,CArchiveIO*>& 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<int,CArchiveIO*> m_Files;
|
||||
int m_Index;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -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<int, QIODevice*> 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;
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
#pragma once
|
||||
#include <private/qabstractfileengine_p.h>
|
||||
#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;
|
||||
};
|
|
@ -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<PROPID,QString> 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
|
|
@ -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 <QLibrary>
|
||||
|
||||
#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
|
|
@ -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
|
|
@ -0,0 +1,193 @@
|
|||
#include "stdafx.h"
|
||||
#include "ArchiveInterface.h"
|
||||
//#include "../Functions.h"
|
||||
#ifdef __APPLE__
|
||||
#include <QCoreApplication>
|
||||
#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<m_Formats.count(); i++)
|
||||
{
|
||||
if(Ext.compare(m_Formats[i].GetMainExt(), Qt::CaseInsensitive) == 0)
|
||||
return i+1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*QList<int> CArchiveInterface::FindByExt(const QString &Ext)
|
||||
{
|
||||
QMutexLocker Locker(&m_Mutex);
|
||||
QList<int> ArcIndex;
|
||||
for(int i=0; i<m_Formats.count(); i++)
|
||||
{
|
||||
if(m_Formats[i].FindExtension(Ext) != -1)
|
||||
ArcIndex.append(i+1);
|
||||
}
|
||||
return ArcIndex;
|
||||
}*/
|
||||
|
||||
QString CArchiveInterface::GetArchiveName(int formatIndex)
|
||||
{
|
||||
QMutexLocker Locker(&m_Mutex);
|
||||
if(formatIndex > 0 && formatIndex <= m_Formats.count())
|
||||
return m_Formats[formatIndex-1].Name;
|
||||
return "";
|
||||
}
|
||||
|
||||
bool CArchiveInterface::CreateInArchive(int formatIndex, CMyComPtr<IInArchive> &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<IOutArchive> &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
|
|
@ -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<CArcExtInfo> 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<int> FindByExt(const QString &Ext);
|
||||
QString GetArchiveName(int formatIndex);
|
||||
|
||||
int GetFormatCount() {return m_Formats.count();}
|
||||
bool CreateInArchive(int formatIndex, CMyComPtr<IInArchive> &archive) const;
|
||||
bool CreateOutArchive(int formatIndex, CMyComPtr<IOutArchive> &archive) const;
|
||||
|
||||
protected:
|
||||
bool CreateArchiveHandler(const CArcInfoEx &ai, void **archive, bool outHandler) const;
|
||||
|
||||
QLibrary m_7z;
|
||||
//QList<CCdrInfo> m_Coders;
|
||||
QVector<CArcInfoEx> m_Formats;
|
||||
CreateObjectFunc createObjectFunc;
|
||||
|
||||
bool m_Operational;
|
||||
mutable QMutex m_Mutex;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -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<IInStream> 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
|
|
@ -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
|
|
@ -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>("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<QString, quint64> C7zWorker::GetFileList()
|
||||
{
|
||||
QMap<QString, quint64> 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<int, QIODevice*> 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<int, QIODevice*> 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<QString, quint64> CRarWorker::GetFileList()
|
||||
{
|
||||
QMap<QString, quint64> 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;
|
||||
}
|
|
@ -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<QString, quint64> 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<QString, quint64> 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<QString, quint64> 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<QString, quint64> 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;
|
||||
};
|
|
@ -0,0 +1,106 @@
|
|||
#include "stdafx.h"
|
||||
#include "ArchiveUpdater.h"
|
||||
#include "Archive.h"
|
||||
|
||||
#ifdef USE_7Z
|
||||
|
||||
CArchiveUpdater::CArchiveUpdater(CArchive* pArchive, const QMap<int,CArchiveIO*>& 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<FILETIME*>(&date);} break;
|
||||
case kpidATime: {quint64 date = m_pArchive->FileProperty(ArcIndex, "ATime").toULongLong(); // ToDo
|
||||
prop = *reinterpret_cast<FILETIME*>(&date);} break;
|
||||
case kpidMTime: {quint64 date = m_pArchive->FileProperty(ArcIndex, "MTime").toULongLong(); // ToDo
|
||||
prop = *reinterpret_cast<FILETIME*>(&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<int, QIODevice*> 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<ISequentialInStream> 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
|
|
@ -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<int,CArchiveIO*>& 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<int,CArchiveIO*> m_Files;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,37 @@
|
|||
#include "stdafx.h"
|
||||
#include "CachedArchive.h"
|
||||
|
||||
#ifdef USE_7Z
|
||||
|
||||
CCachedArchive::CCachedArchive(const QString &ArchivePath)
|
||||
: CArchive(ArchivePath)
|
||||
{
|
||||
}
|
||||
|
||||
bool CCachedArchive::Extract(QMap<int, QIODevice*> *FileList, bool bDelete)
|
||||
{
|
||||
QMap<int, QIODevice*> 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
|
|
@ -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<int, QIODevice*> *FileList, bool bDelete = true) {LogError("Cachen archives can not be updated"); return false;}
|
||||
bool Extract(QMap<int, QIODevice*> *FileList, bool bDelete = true);
|
||||
|
||||
protected:
|
||||
|
||||
QMap<int, QByteArray> m_CacheMap;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -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;
|
||||
}
|
|
@ -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<QFile*> m_FileParts;
|
||||
|
||||
quint64 m_Position;
|
||||
int m_Index;
|
||||
};
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
#pragma once
|
||||
|
||||
#include "../../mischelpers_global.h"
|
||||
|
||||
#include <QMutex>
|
||||
#include <QWaitCondition>
|
||||
|
||||
/**********************************************************************************************
|
||||
* 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;
|
||||
};
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -189,6 +189,16 @@
|
|||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Archive\Archive.cpp" />
|
||||
<ClCompile Include="Archive\ArchiveExtractor.cpp" />
|
||||
<ClCompile Include="Archive\ArchiveFS.cpp" />
|
||||
<ClCompile Include="Archive\ArchiveHelper.cpp" />
|
||||
<ClCompile Include="Archive\ArchiveInterface.cpp" />
|
||||
<ClCompile Include="Archive\ArchiveOpener.cpp" />
|
||||
<ClCompile Include="Archive\ArchiveThread.cpp" />
|
||||
<ClCompile Include="Archive\ArchiveUpdater.cpp" />
|
||||
<ClCompile Include="Archive\CachedArchive.cpp" />
|
||||
<ClCompile Include="Archive\SplitFile.cpp" />
|
||||
<ClCompile Include="Common\CheckableMessageBox.cpp" />
|
||||
<ClCompile Include="Common\ComboInputDialog.cpp" />
|
||||
<ClCompile Include="Common\Common.cpp" />
|
||||
|
@ -198,6 +208,7 @@
|
|||
<ClCompile Include="Common\ItemChooser.cpp" />
|
||||
<ClCompile Include="Common\KeyValueInputDialog.cpp" />
|
||||
<ClCompile Include="Common\ListItemModel.cpp" />
|
||||
<ClCompile Include="Common\MT\ThreadLock.cpp" />
|
||||
<ClCompile Include="Common\MultiLineInputDialog.cpp" />
|
||||
<ClCompile Include="Common\OtherFunctions.cpp" />
|
||||
<ClCompile Include="Common\PanelView.cpp" />
|
||||
|
@ -222,6 +233,17 @@
|
|||
<QtMoc Include="Common\CheckableMessageBox.h" />
|
||||
<QtMoc Include="Common\ComboInputDialog.h" />
|
||||
<QtMoc Include="Common\CheckList.h" />
|
||||
<ClInclude Include="Archive\Archive.h" />
|
||||
<ClInclude Include="Archive\ArchiveExtractor.h" />
|
||||
<ClInclude Include="Archive\ArchiveFS.h" />
|
||||
<ClInclude Include="Archive\ArchiveHelper.h" />
|
||||
<ClInclude Include="Archive\ArchiveInterface.h" />
|
||||
<ClInclude Include="Archive\ArchiveIO.h" />
|
||||
<ClInclude Include="Archive\ArchiveOpener.h" />
|
||||
<QtMoc Include="Archive\ArchiveThread.h" />
|
||||
<ClInclude Include="Archive\ArchiveUpdater.h" />
|
||||
<ClInclude Include="Archive\CachedArchive.h" />
|
||||
<QtMoc Include="Archive\SplitFile.h" />
|
||||
<ClInclude Include="Common\Common.h" />
|
||||
<ClInclude Include="Common\DebugHelpers.h" />
|
||||
<ClInclude Include="Common\ExitDialog.h" />
|
||||
|
@ -244,6 +266,7 @@
|
|||
<QtMoc Include="Common\TreeItemModel.h" />
|
||||
<QtMoc Include="Common\TreeViewEx.h" />
|
||||
<QtMoc Include="Common\TreeWidgetEx.h" />
|
||||
<ClInclude Include="Common\MT\ThreadLock.h" />
|
||||
<QtMoc Include="Common\NeonEffect.h" />
|
||||
<ClInclude Include="Common\OtherFunctions.h" />
|
||||
<ClInclude Include="Common\qRC4.h" />
|
||||
|
|
|
@ -22,6 +22,12 @@
|
|||
<Filter Include="Common">
|
||||
<UniqueIdentifier>{964acff8-ecee-4dfc-939d-e2406a533100}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Archive">
|
||||
<UniqueIdentifier>{1e331c49-0544-4a02-83e5-e47774ab5fac}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Common\MT">
|
||||
<UniqueIdentifier>{55ef64ac-4671-4600-8e4a-ca56d181c6ec}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="MiscHelpers.cpp">
|
||||
|
@ -93,6 +99,39 @@
|
|||
<ClCompile Include="Common\OtherFunctions.cpp">
|
||||
<Filter>Common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Archive\Archive.cpp">
|
||||
<Filter>Archive</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Archive\ArchiveExtractor.cpp">
|
||||
<Filter>Archive</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Archive\ArchiveHelper.cpp">
|
||||
<Filter>Archive</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Archive\ArchiveInterface.cpp">
|
||||
<Filter>Archive</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Archive\ArchiveOpener.cpp">
|
||||
<Filter>Archive</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Archive\ArchiveUpdater.cpp">
|
||||
<Filter>Archive</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Archive\CachedArchive.cpp">
|
||||
<Filter>Archive</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Archive\SplitFile.cpp">
|
||||
<Filter>Archive</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Archive\ArchiveThread.cpp">
|
||||
<Filter>Archive</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Common\MT\ThreadLock.cpp">
|
||||
<Filter>Common\MT</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Archive\ArchiveFS.cpp">
|
||||
<Filter>Archive</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="MiscHelpers.h">
|
||||
|
@ -128,6 +167,36 @@
|
|||
<ClInclude Include="Common\OtherFunctions.h">
|
||||
<Filter>Common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Archive\Archive.h">
|
||||
<Filter>Archive</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Archive\ArchiveExtractor.h">
|
||||
<Filter>Archive</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Archive\ArchiveHelper.h">
|
||||
<Filter>Archive</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Archive\ArchiveInterface.h">
|
||||
<Filter>Archive</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Archive\ArchiveIO.h">
|
||||
<Filter>Archive</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Archive\ArchiveOpener.h">
|
||||
<Filter>Archive</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Archive\ArchiveUpdater.h">
|
||||
<Filter>Archive</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Archive\CachedArchive.h">
|
||||
<Filter>Archive</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Common\MT\ThreadLock.h">
|
||||
<Filter>Common\MT</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Archive\ArchiveFS.h">
|
||||
<Filter>Archive</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="mischelpers_global.h">
|
||||
|
@ -195,6 +264,12 @@
|
|||
<QtMoc Include="Common\CheckList.h">
|
||||
<Filter>Common</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="Archive\SplitFile.h">
|
||||
<Filter>Archive</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="Archive\ArchiveThread.h">
|
||||
<Filter>Archive</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="Common\NeonEffect.h">
|
||||
<Filter>Common</Filter>
|
||||
</QtMoc>
|
||||
|
|
|
@ -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 <QVariantAnimation>
|
||||
#include <QSessionManager>
|
||||
|
||||
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<QAction*>(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<CSandBoxPlus>();
|
||||
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<SB_STATUS>() << 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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
#include "BoxMonitor.h"
|
||||
#include "..\MiscHelpers\Common\OtherFunctions.h"
|
||||
#include "../QSbieAPI/SbieUtils.h"
|
||||
#include "../MiscHelpers/Archive/Archive.h"
|
||||
#include <QtConcurrent>
|
||||
|
||||
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<int, QIODevice*> 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<int, QIODevice*> 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");
|
||||
|
|
|
@ -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<QSharedPointer<CBoxJob>> m_JobQueue;
|
||||
|
||||
bool m_bLogApiFound;
|
||||
|
|
|
@ -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<CSandBoxPtr>& 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<CSandBoxPlus>();
|
||||
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("_", " ");
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue