Advertisement
Guest User

Untitled

a guest
Mar 18th, 2022
132
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 27.25 KB | None | 0 0
  1. #include "7zip/CPP/Archive/IArchive.h"
  2. #include "7zip/CPP/ICoder.h"
  3. #include "7zip/CPP/IPassword.h"
  4.  
  5. class CInStream : public IInStream, public IStreamGetProps
  6. {
  7. public:
  8.     CInStream(const std::wstring& FilePath) : m_RefCount(1), m_FilePath(FilePath), m_FileHandle(INVALID_HANDLE_VALUE)
  9.     {
  10.         m_FileHandle = CreateFileW(FilePath.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
  11.     }
  12.     virtual ~CInStream()
  13.     {
  14.         if (m_FileHandle != INVALID_HANDLE_VALUE)
  15.         {
  16.             CloseHandle(m_FileHandle);
  17.             m_FileHandle = INVALID_HANDLE_VALUE;
  18.         }
  19.     }
  20.     static HRESULT Create(const std::wstring& FilePath, REFIID riid, void** ppvObject)
  21.     {
  22.         CInStream* InStream = new CInStream(FilePath);
  23.         HRESULT hr = InStream->QueryInterface(riid, ppvObject);
  24.         InStream->Release();
  25.         InStream = NULL;
  26.         return hr;
  27.     }
  28.     // IInStream
  29.     STDMETHODIMP Seek(Int64 Offset, UInt32 Origin, UInt64* NewPosition)
  30.     {
  31.         if (m_FileHandle == INVALID_HANDLE_VALUE)
  32.         {
  33.             return E_FAIL;
  34.         }
  35.         BOOL Success = SetFilePointerEx(m_FileHandle, *reinterpret_cast<LARGE_INTEGER*>(&Offset), reinterpret_cast<LARGE_INTEGER*>(NewPosition), Origin);
  36.         if (!Success)
  37.         {
  38.             DWORD LastError = GetLastError();
  39.             return HRESULT_FROM_WIN32(LastError);
  40.         }
  41.         return S_OK;
  42.     }
  43.     // ISequentialInStream
  44.     STDMETHODIMP Read(void* Buffer, UInt32 Length, UInt32* LengthRead)
  45.     {
  46.         if (m_FileHandle == INVALID_HANDLE_VALUE)
  47.         {
  48.             return E_FAIL;
  49.         }
  50.         BOOL Success = ReadFile(m_FileHandle, Buffer, Length, reinterpret_cast<LPDWORD>(LengthRead), NULL);
  51.         if (!Success)
  52.         {
  53.             DWORD LastError = GetLastError();
  54.             return HRESULT_FROM_WIN32(LastError);
  55.         }
  56.         return S_OK;
  57.     }
  58.     // IStreamGetProps
  59.     STDMETHODIMP GetProps(UInt64* Size, FILETIME* CreationTime, FILETIME* LastAccessTime, FILETIME* LastWriteTime, UInt32* Attributes)
  60.     {
  61.         if (m_FileHandle == INVALID_HANDLE_VALUE)
  62.         {
  63.             return E_FAIL;
  64.         }
  65.         if (Size)
  66.         {
  67.             BOOL Success = GetFileSizeEx(m_FileHandle, reinterpret_cast<LARGE_INTEGER*>(Size));
  68.             if (!Success)
  69.             {
  70.                 DWORD LastError = GetLastError();
  71.                 return HRESULT_FROM_WIN32(LastError);
  72.             }
  73.         }
  74.         if (CreationTime || LastAccessTime || LastWriteTime)
  75.         {
  76.             BOOL Success = GetFileTime(m_FileHandle, CreationTime, LastAccessTime, LastWriteTime);
  77.             if (!Success)
  78.             {
  79.                 DWORD LastError = GetLastError();
  80.                 return HRESULT_FROM_WIN32(LastError);
  81.             }
  82.         }
  83.         if (Attributes)
  84.         {
  85.             *Attributes = GetFileAttributesW(m_FilePath.c_str());
  86.             if (*Attributes == INVALID_FILE_ATTRIBUTES)
  87.             {
  88.                 DWORD LastError = GetLastError();
  89.                 return HRESULT_FROM_WIN32(LastError);
  90.             }
  91.         }
  92.         return S_OK;
  93.     }
  94.     // IUnknown
  95.     STDMETHODIMP QueryInterface(REFIID riid, void** ppvObject)
  96.     {
  97.         if (!ppvObject)
  98.         {
  99.             return E_POINTER;
  100.         }
  101.         if (IsEqualIID(riid, IID_IInStream))
  102.         {
  103.             *ppvObject = static_cast<IInStream*>(this);
  104.             AddRef();
  105.             return S_OK;
  106.         }
  107.         if (IsEqualIID(riid, IID_ISequentialInStream))
  108.         {
  109.             *ppvObject = static_cast<ISequentialInStream*>(this);
  110.             AddRef();
  111.             return S_OK;
  112.         }
  113.         if (IsEqualIID(riid, IID_IStreamGetProps))
  114.         {
  115.             *ppvObject = static_cast<IStreamGetProps*>(this);
  116.             AddRef();
  117.             return S_OK;
  118.         }
  119.         if (IsEqualIID(riid, IID_IUnknown))
  120.         {
  121.             *ppvObject = static_cast<IUnknown*>(static_cast<IInStream*>(this));
  122.             AddRef();
  123.             return S_OK;
  124.         }
  125.         WCHAR GuidString[64];
  126.         StringFromGUID2(riid, GuidString, ARRAYSIZE(GuidString));
  127.         wprintf_s(L"CInStream::QueryInterface(%ls)\n", GuidString);
  128.         *ppvObject = NULL;
  129.         return E_NOINTERFACE;
  130.     }
  131.     STDMETHODIMP_(ULONG) AddRef()
  132.     {
  133.         ++m_RefCount;
  134.         return m_RefCount;
  135.     }
  136.     STDMETHODIMP_(ULONG) Release()
  137.     {
  138.         --m_RefCount;
  139.         if (!m_RefCount)
  140.         {
  141.             delete this;
  142.             return 0;
  143.         }
  144.         return m_RefCount;
  145.     }
  146. protected:
  147.     ULONG m_RefCount;
  148.     std::wstring m_FilePath;
  149.     HANDLE m_FileHandle;
  150. };
  151.  
  152. class COutStream : public IOutStream
  153. {
  154. public:
  155.     COutStream(const std::wstring& FilePath) : m_RefCount(1), m_FilePath(FilePath), m_FileHandle(INVALID_HANDLE_VALUE)
  156.     {
  157.         m_FileHandle = CreateFileW(FilePath.c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  158.     }
  159.     virtual ~COutStream()
  160.     {
  161.         if (m_FileHandle != INVALID_HANDLE_VALUE)
  162.         {
  163.             CloseHandle(m_FileHandle);
  164.             m_FileHandle = INVALID_HANDLE_VALUE;
  165.         }
  166.     }
  167.     static HRESULT Create(const std::wstring& FilePath, REFIID riid, void** ppvObject)
  168.     {
  169.         COutStream* OutStream = new COutStream(FilePath);
  170.         HRESULT hr = OutStream->QueryInterface(riid, ppvObject);
  171.         OutStream->Release();
  172.         OutStream = NULL;
  173.         return hr;
  174.     }
  175.     // IOutStream
  176.     STDMETHODIMP Seek(Int64 Offset, UInt32 Origin, UInt64* NewPosition)
  177.     {
  178.         if (m_FileHandle == INVALID_HANDLE_VALUE)
  179.         {
  180.             return E_FAIL;
  181.         }
  182.         BOOL Success = SetFilePointerEx(m_FileHandle, *reinterpret_cast<LARGE_INTEGER*>(&Offset), reinterpret_cast<LARGE_INTEGER*>(NewPosition), Origin);
  183.         if (!Success)
  184.         {
  185.             DWORD LastError = GetLastError();
  186.             return HRESULT_FROM_WIN32(LastError);
  187.         }
  188.         return S_OK;
  189.     }
  190.     STDMETHODIMP SetSize(UInt64 NewSize)
  191.     {
  192.         if (m_FileHandle == INVALID_HANDLE_VALUE)
  193.         {
  194.             return E_FAIL;
  195.         }
  196.         BOOL Success = SetFilePointerEx(m_FileHandle, *reinterpret_cast<LARGE_INTEGER*>(&NewSize), NULL, FILE_BEGIN);
  197.         if (!Success)
  198.         {
  199.             DWORD LastError = GetLastError();
  200.             return HRESULT_FROM_WIN32(LastError);
  201.         }
  202.         Success = SetEndOfFile(m_FileHandle);
  203.         if (!Success)
  204.         {
  205.             DWORD LastError = GetLastError();
  206.             return HRESULT_FROM_WIN32(LastError);
  207.         }
  208.         return S_OK;
  209.     }
  210.     // ISequentialOutStream
  211.     STDMETHODIMP Write(const void* Buffer, UInt32 Length, UInt32* LengthWritten)
  212.     {
  213.         if (m_FileHandle == INVALID_HANDLE_VALUE)
  214.         {
  215.             return E_FAIL;
  216.         }
  217.         BOOL Success = WriteFile(m_FileHandle, Buffer, Length, reinterpret_cast<LPDWORD>(LengthWritten), NULL);
  218.         if (!Success)
  219.         {
  220.             DWORD LastError = GetLastError();
  221.             return HRESULT_FROM_WIN32(LastError);
  222.         }
  223.         return S_OK;
  224.     }
  225.     // IUnknown
  226.     STDMETHODIMP QueryInterface(REFIID riid, void** ppvObject)
  227.     {
  228.         if (!ppvObject)
  229.         {
  230.             return E_POINTER;
  231.         }
  232.         if (IsEqualIID(riid, IID_IOutStream))
  233.         {
  234.             *ppvObject = static_cast<IOutStream*>(this);
  235.             AddRef();
  236.             return S_OK;
  237.         }
  238.         if (IsEqualIID(riid, IID_ISequentialOutStream))
  239.         {
  240.             *ppvObject = static_cast<ISequentialOutStream*>(this);
  241.             AddRef();
  242.             return S_OK;
  243.         }
  244.         if (IsEqualIID(riid, IID_IUnknown))
  245.         {
  246.             *ppvObject = static_cast<IUnknown*>(this);
  247.             AddRef();
  248.             return S_OK;
  249.         }
  250.         WCHAR GuidString[64];
  251.         StringFromGUID2(riid, GuidString, ARRAYSIZE(GuidString));
  252.         wprintf_s(L"COutStream::QueryInterface(%ls)\n", GuidString);
  253.         *ppvObject = NULL;
  254.         return E_NOINTERFACE;
  255.     }
  256.     STDMETHODIMP_(ULONG) AddRef()
  257.     {
  258.         ++m_RefCount;
  259.         return m_RefCount;
  260.     }
  261.     STDMETHODIMP_(ULONG) Release()
  262.     {
  263.         --m_RefCount;
  264.         if (!m_RefCount)
  265.         {
  266.             delete this;
  267.             return 0;
  268.         }
  269.         return m_RefCount;
  270.     }
  271. protected:
  272.     ULONG m_RefCount;
  273.     std::wstring m_FilePath;
  274.     HANDLE m_FileHandle;
  275. };
  276.  
  277. class CArchiveOpenCallback : public IArchiveOpenCallback
  278. {
  279. public:
  280.     CArchiveOpenCallback() : m_RefCount(1) {}
  281.     virtual ~CArchiveOpenCallback() {}
  282.     static HRESULT Create(REFIID riid, void** ppvObject)
  283.     {
  284.         CArchiveOpenCallback* ArchiveOpenCallback = new CArchiveOpenCallback();
  285.         HRESULT hr = ArchiveOpenCallback->QueryInterface(riid, ppvObject);
  286.         ArchiveOpenCallback->Release();
  287.         ArchiveOpenCallback = NULL;
  288.         return hr;
  289.     }
  290.     // IArchiveOpenCallback
  291.     STDMETHODIMP SetTotal(const UInt64* FileCount, const UInt64* ByteCount)
  292.     {
  293.         return S_OK;
  294.     }
  295.     STDMETHODIMP SetCompleted(const UInt64* FileCount, const UInt64* ByteCount)
  296.     {
  297.         return S_OK;
  298.     }
  299.     // IUnknown
  300.     STDMETHODIMP QueryInterface(REFIID riid, void** ppvObject)
  301.     {
  302.         if (!ppvObject)
  303.         {
  304.             return E_POINTER;
  305.         }
  306.         if (IsEqualIID(riid, IID_IArchiveOpenCallback))
  307.         {
  308.             *ppvObject = static_cast<IArchiveOpenCallback*>(this);
  309.             AddRef();
  310.             return S_OK;
  311.         }
  312.         if (IsEqualIID(riid, IID_IUnknown))
  313.         {
  314.             *ppvObject = static_cast<IUnknown*>(this);
  315.             AddRef();
  316.             return S_OK;
  317.         }
  318.         WCHAR GuidString[64];
  319.         StringFromGUID2(riid, GuidString, ARRAYSIZE(GuidString));
  320.         wprintf_s(L"CArchiveOpenCallback::QueryInterface(%ls)\n", GuidString);
  321.         *ppvObject = NULL;
  322.         return E_NOINTERFACE;
  323.     }
  324.     STDMETHODIMP_(ULONG) AddRef()
  325.     {
  326.         ++m_RefCount;
  327.         return m_RefCount;
  328.     }
  329.     STDMETHODIMP_(ULONG) Release()
  330.     {
  331.         --m_RefCount;
  332.         if (!m_RefCount)
  333.         {
  334.             delete this;
  335.             return 0;
  336.         }
  337.         return m_RefCount;
  338.     }
  339. protected:
  340.     ULONG m_RefCount;
  341. };
  342.  
  343. class CArchiveExtractCallback : public IArchiveExtractCallback, public ICompressProgressInfo
  344. {
  345. public:
  346.     CArchiveExtractCallback(const std::wstring& FolderPath, IInArchive* InArchive) : m_RefCount(1), m_FolderPath(FolderPath), m_InArchive(InArchive)
  347.     {
  348.         if (m_InArchive)
  349.         {
  350.             m_InArchive->AddRef();
  351.         }
  352.     }
  353.     virtual ~CArchiveExtractCallback()
  354.     {
  355.         if (m_InArchive)
  356.         {
  357.             m_InArchive->Release();
  358.             m_InArchive = NULL;
  359.         }
  360.     }
  361.     static HRESULT Create(const std::wstring& FolderPath, IInArchive* InArchive, REFIID riid, void** ppvObject)
  362.     {
  363.         CArchiveExtractCallback* ArchiveExtractCallback = new CArchiveExtractCallback(FolderPath, InArchive);
  364.         HRESULT hr = ArchiveExtractCallback->QueryInterface(riid, ppvObject);
  365.         ArchiveExtractCallback->Release();
  366.         ArchiveExtractCallback = NULL;
  367.         return hr;
  368.     }
  369.     // IArchiveExtractCallback
  370.     STDMETHODIMP GetStream(UInt32 ItemIndex, ISequentialOutStream** OutStream, Int32 ExtractMode)
  371.     {
  372.         std::wstring RelativePath;
  373.         PROPVARIANT PropValue;
  374.         PropVariantInit(&PropValue);
  375.         HRESULT hr = m_InArchive->GetProperty(ItemIndex, kpidPath, &PropValue);
  376.         RelativePath = PropValue.bstrVal;
  377.         PropVariantClear(&PropValue);
  378.  
  379.         std::wstring FilePath = Utils::AppendPaths(m_FolderPath, RelativePath);
  380.         std::wstring FolderPath, FileName;
  381.         Utils::SplitIntoDirectoryAndFile(FilePath, FolderPath, FileName);
  382.         Utils::MakeDirectories(FolderPath);
  383.  
  384.         hr = COutStream::Create(FilePath, IID_ISequentialOutStream, (void**)OutStream);
  385.  
  386.         return hr;
  387.     }
  388.     STDMETHODIMP PrepareOperation(Int32 ExtractMode)
  389.     {
  390.         // NOTE: NArchive::NExtract::NAskMode
  391.         return S_OK;
  392.     }
  393.     STDMETHODIMP SetOperationResult(Int32 OperationResult)
  394.     {
  395.         // NOTE: NArchive::NExtract::NOperationResult
  396.         return S_OK;
  397.     }
  398.     // IProgress
  399.     STDMETHODIMP SetTotal(UInt64 Total)
  400.     {
  401.         return S_OK;
  402.     }
  403.     STDMETHODIMP SetCompleted(const UInt64* Completed)
  404.     {
  405.         return S_OK;
  406.     }
  407.     // ICompressProgressInfo
  408.     STDMETHODIMP SetRatioInfo(const UInt64* InSize, const UInt64* OutSize)
  409.     {
  410.         return S_OK;
  411.     }
  412.     // IUnknown
  413.     STDMETHODIMP QueryInterface(REFIID riid, void** ppvObject)
  414.     {
  415.         if (!ppvObject)
  416.         {
  417.             return E_POINTER;
  418.         }
  419.         if (IsEqualIID(riid, IID_IArchiveExtractCallback))
  420.         {
  421.             *ppvObject = static_cast<IArchiveExtractCallback*>(this);
  422.             AddRef();
  423.             return S_OK;
  424.         }
  425.         if (IsEqualIID(riid, IID_IProgress))
  426.         {
  427.             *ppvObject = static_cast<IProgress*>(this);
  428.             AddRef();
  429.             return S_OK;
  430.         }
  431.         if (IsEqualIID(riid, IID_ICompressProgressInfo))
  432.         {
  433.             *ppvObject = static_cast<ICompressProgressInfo*>(this);
  434.             AddRef();
  435.             return S_OK;
  436.         }
  437.         if (IsEqualIID(riid, IID_IUnknown))
  438.         {
  439.             *ppvObject = static_cast<IUnknown*>(static_cast<IArchiveExtractCallback*>(this));
  440.             AddRef();
  441.             return S_OK;
  442.         }
  443.         WCHAR GuidString[64];
  444.         StringFromGUID2(riid, GuidString, ARRAYSIZE(GuidString));
  445.         wprintf_s(L"CArchiveExtractCallback::QueryInterface(%ls)\n", GuidString);
  446.         *ppvObject = NULL;
  447.         return E_NOINTERFACE;
  448.     }
  449.     STDMETHODIMP_(ULONG) AddRef()
  450.     {
  451.         ++m_RefCount;
  452.         return m_RefCount;
  453.     }
  454.     STDMETHODIMP_(ULONG) Release()
  455.     {
  456.         --m_RefCount;
  457.         if (!m_RefCount)
  458.         {
  459.             delete this;
  460.             return 0;
  461.         }
  462.         return m_RefCount;
  463.     }
  464. protected:
  465.     ULONG m_RefCount;
  466.     std::wstring m_FolderPath;
  467.     IInArchive* m_InArchive;
  468. };
  469.  
  470. class CArchiveUpdateCallback : public IArchiveUpdateCallback, public ICompressProgressInfo, public ICryptoGetTextPassword2, public IArchiveUpdateCallbackFile
  471. {
  472. public:
  473.     CArchiveUpdateCallback(const std::vector<std::pair<std::wstring, std::wstring>>& FileList) : m_RefCount(1), m_FileList(FileList) {}
  474.     virtual ~CArchiveUpdateCallback() {}
  475.     static HRESULT Create(const std::vector<std::pair<std::wstring, std::wstring>>& FileList, REFIID riid, void** ppvObject)
  476.     {
  477.         CArchiveUpdateCallback* ArchiveUpdateCallback = new CArchiveUpdateCallback(FileList);
  478.         HRESULT hr = ArchiveUpdateCallback->QueryInterface(riid, ppvObject);
  479.         ArchiveUpdateCallback->Release();
  480.         ArchiveUpdateCallback = NULL;
  481.         return hr;
  482.     }
  483.     // IArchiveUpdateCallback
  484.     STDMETHODIMP GetUpdateItemInfo(UInt32 ItemIndex, Int32* NewData, Int32* NewProps, UInt32* IndexInArchive)
  485.     {
  486.         *NewData = 1;
  487.         *NewProps = 1;
  488.         *IndexInArchive = -1;
  489.         return S_OK;
  490.     }
  491.     STDMETHODIMP GetProperty(UInt32 Index, PROPID PropID, PROPVARIANT* PropValue)
  492.     {
  493.         const std::wstring& FilePath = m_FileList[Index].first;
  494.         const std::wstring& ItemPath = m_FileList[Index].second;
  495.         switch (PropID)
  496.         {
  497.         case kpidAttrib:
  498.             V_VT(PropValue) = VT_UI4;
  499.             V_UI4(PropValue) = FILE_ATTRIBUTE_NORMAL;
  500.             break;
  501.         case kpidPath:
  502.             V_VT(PropValue) = VT_BSTR;
  503.             V_BSTR(PropValue) = SysAllocString(ItemPath.c_str());
  504.             break;
  505.         case kpidIsDir:
  506.             V_VT(PropValue) = VT_BOOL;
  507.             V_BOOL(PropValue) = VARIANT_FALSE;
  508.             break;
  509.         case kpidTimeType:
  510.             V_VT(PropValue) = VT_UI4;
  511.             V_UI4(PropValue) = 0; // 0 = NTFS, 1 = UNIX, 2 = DOS
  512.             break;
  513.         case kpidMTime:
  514.             V_VT(PropValue) = VT_FILETIME;
  515.             Utils::GetTime(FilePath, NULL, NULL, reinterpret_cast<uint64_t*>(&PropValue->filetime));
  516.             break;
  517.         case kpidATime:
  518.             V_VT(PropValue) = VT_FILETIME;
  519.             Utils::GetTime(FilePath, NULL, reinterpret_cast<uint64_t*>(&PropValue->filetime), NULL);
  520.             break;
  521.         case kpidCTime:
  522.             V_VT(PropValue) = VT_FILETIME;
  523.             Utils::GetTime(FilePath, reinterpret_cast<uint64_t*>(&PropValue->filetime), NULL, NULL);
  524.             break;
  525.         case kpidComment:
  526.             break;
  527.         case kpidSize:
  528.             V_VT(PropValue) = VT_UI8;
  529.             PropValue->uhVal.QuadPart = Utils::GetSize(FilePath);
  530.             break;
  531.         default:
  532.             _ASSERT(FALSE);
  533.             break;
  534.         }
  535.         return S_OK;
  536.     }
  537.     STDMETHODIMP GetStream(UInt32 ItemIndex, ISequentialInStream** InStream)
  538.     {
  539.         const std::wstring& FilePath = m_FileList[ItemIndex].first;
  540.         HRESULT hr = CInStream::Create(FilePath, IID_ISequentialInStream, (void**)InStream);
  541.         return hr;
  542.     }
  543.     STDMETHODIMP SetOperationResult(Int32 OperationResult)
  544.     {
  545.         // NOTE: NArchive::NUpdate::NOperationResult
  546.         return S_OK;
  547.     }
  548.     // IProgress
  549.     STDMETHODIMP SetTotal(UInt64 Total)
  550.     {
  551.         return S_OK;
  552.     }
  553.     STDMETHODIMP SetCompleted(const UInt64* Completed)
  554.     {
  555.         return S_OK;
  556.     }
  557.     // ICompressProgressInfo
  558.     STDMETHODIMP SetRatioInfo(const UInt64* InSize, const UInt64* OutSize)
  559.     {
  560.         return S_OK;
  561.     }
  562.     // ICryptoGetTextPassword2
  563.     STDMETHODIMP CryptoGetTextPassword2(Int32* PasswordIsDefined, BSTR* Password)
  564.     {
  565.         *PasswordIsDefined = 0;
  566.         *Password = NULL;
  567.         // TODO: password
  568.         //*PasswordIsDefined = 1;
  569.         //*Password = SysAllocString(L"password");
  570.         return S_OK;
  571.     }
  572.     // IArchiveUpdateCallbackFile
  573.     STDMETHODIMP GetStream2(UInt32 Index, ISequentialInStream** InStream, UInt32 NotifyOp)
  574.     {
  575.         return E_NOTIMPL;
  576.     }
  577.     STDMETHODIMP ReportOperation(UInt32 IndexType, UInt32 Index, UInt32 NotifyOperation)
  578.     {
  579.         // NOTE: IndexType = NArchive::NEventIndexType
  580.         // NOTE: NotifyOperation = NUpdateNotifyOp
  581.         return E_NOTIMPL;
  582.     }
  583.     // IUnknown
  584.     STDMETHODIMP QueryInterface(REFIID riid, void** ppvObject)
  585.     {
  586.         if (!ppvObject)
  587.         {
  588.             return E_POINTER;
  589.         }
  590.         if (IsEqualIID(riid, IID_IArchiveUpdateCallback))
  591.         {
  592.             *ppvObject = static_cast<IArchiveUpdateCallback*>(this);
  593.             AddRef();
  594.             return S_OK;
  595.         }
  596.         if (IsEqualIID(riid, IID_IProgress))
  597.         {
  598.             *ppvObject = static_cast<IProgress*>(this);
  599.             AddRef();
  600.             return S_OK;
  601.         }
  602.         if (IsEqualIID(riid, IID_ICompressProgressInfo))
  603.         {
  604.             *ppvObject = static_cast<ICompressProgressInfo*>(this);
  605.             AddRef();
  606.             return S_OK;
  607.         }
  608.         if (IsEqualIID(riid, IID_ICryptoGetTextPassword2))
  609.         {
  610.             *ppvObject = static_cast<ICryptoGetTextPassword2*>(this);
  611.             AddRef();
  612.             return S_OK;
  613.         }
  614.         if (IsEqualIID(riid, IID_IArchiveUpdateCallbackFile))
  615.         {
  616.             *ppvObject = static_cast<IArchiveUpdateCallbackFile*>(this);
  617.             AddRef();
  618.             return S_OK;
  619.         }
  620.         if (IsEqualIID(riid, IID_IUnknown))
  621.         {
  622.             *ppvObject = static_cast<IUnknown*>(static_cast<IArchiveUpdateCallback*>(this));
  623.             AddRef();
  624.             return S_OK;
  625.         }
  626.         WCHAR GuidString[64];
  627.         StringFromGUID2(riid, GuidString, ARRAYSIZE(GuidString));
  628.         wprintf_s(L"CArchiveUpdateCallback::QueryInterface(%ls)\n", GuidString);
  629.         *ppvObject = NULL;
  630.         return E_NOINTERFACE;
  631.     }
  632.     STDMETHODIMP_(ULONG) AddRef()
  633.     {
  634.         ++m_RefCount;
  635.         return m_RefCount;
  636.     }
  637.     STDMETHODIMP_(ULONG) Release()
  638.     {
  639.         --m_RefCount;
  640.         if (!m_RefCount)
  641.         {
  642.             delete this;
  643.             return 0;
  644.         }
  645.         return m_RefCount;
  646.     }
  647. protected:
  648.     ULONG m_RefCount;
  649.     std::vector<std::pair<std::wstring, std::wstring>> m_FileList;
  650. };
  651.  
  652. // {23170F69-40C1-278A-1000-000110010000}
  653. static const GUID ZipHandlerClassId = { 0x23170F69, 0x40C1, 0x278A, { 0x10, 0x00, 0x00, 0x01, 0x10, 0x01, 0x00, 0x00 } };
  654.  
  655. class SevenZip
  656. {
  657. public:
  658.     SevenZip(const std::wstring& FilePath) : m_FilePath(FilePath), m_ModuleHandle(NULL), m_CreateObject(NULL)
  659.     {
  660.         if (FilePath.empty())
  661.         {
  662.             throw std::exception("FilePath is empty.");
  663.         }
  664.         m_ModuleHandle = LoadLibraryW(FilePath.c_str());
  665.         if (!m_ModuleHandle)
  666.         {
  667.             DWORD LastError = GetLastError();
  668.             char Message[512];
  669.             sprintf_s(Message, "LoadLibraryW() failed: LastError=%u.", LastError);
  670.             throw std::exception(Message);
  671.         }
  672.         m_CreateObject = reinterpret_cast<Func_CreateObject>(GetProcAddress(m_ModuleHandle, "CreateObject"));
  673.         if (!m_CreateObject)
  674.         {
  675.             DWORD LastError = GetLastError();
  676.             FreeLibrary(m_ModuleHandle);
  677.             m_ModuleHandle = NULL;
  678.             char Message[512];
  679.             sprintf_s(Message, "GetProcAddress() failed: LastError=%u.", LastError);
  680.             throw std::exception(Message);
  681.         }
  682.     }
  683.     virtual ~SevenZip()
  684.     {
  685.         if (m_ModuleHandle)
  686.         {
  687.             FreeLibrary(m_ModuleHandle);
  688.             m_ModuleHandle = NULL;
  689.         }
  690.     }
  691.     void Extract(const std::wstring& FilePath, const std::wstring& FolderPath)
  692.     {
  693.         if (!m_CreateObject)
  694.         {
  695.             throw std::exception("Not initialized.");
  696.         }
  697.         char Message[512];
  698.         IInStream* InStream = NULL;
  699.         HRESULT hr = CInStream::Create(FilePath, IID_IInStream, (void**)&InStream);
  700.         if (SUCCEEDED(hr))
  701.         {
  702.             IInArchive* InArchive = NULL;
  703.             HRESULT hr = m_CreateObject(&ZipHandlerClassId, &IID_IInArchive, (void**)&InArchive);
  704.             if (SUCCEEDED(hr))
  705.             {
  706.                 IArchiveOpenCallback* ArchiveOpenCallback = NULL;
  707.                 hr = CArchiveOpenCallback::Create(IID_IArchiveOpenCallback, (void**)&ArchiveOpenCallback);
  708.                 if (ArchiveOpenCallback)
  709.                 {
  710.                     hr = InArchive->Open(InStream, NULL, ArchiveOpenCallback);
  711.                     if (SUCCEEDED(hr))
  712.                     {
  713.                         IArchiveExtractCallback* ArchiveExtractCallback = NULL;
  714.                         hr = CArchiveExtractCallback::Create(FolderPath, InArchive, IID_IArchiveExtractCallback, (void**)&ArchiveExtractCallback);
  715.                         if (ArchiveExtractCallback)
  716.                         {
  717.                             hr = InArchive->Extract(NULL, -1, 0, ArchiveExtractCallback);
  718.                             if (!SUCCEEDED(hr))
  719.                             {
  720.                                 sprintf_s(Message, "IInArchive::Extract() failed: hr=0x%.08X.", hr);
  721.                             }
  722.                             ArchiveExtractCallback->Release();
  723.                             ArchiveExtractCallback = NULL;
  724.                         }
  725.                         else
  726.                         {
  727.                             sprintf_s(Message, "CArchiveExtractCallback::Create() failed: hr=0x%.08X.", hr);
  728.                         }
  729.                         InArchive->Close();
  730.                     }
  731.                     else
  732.                     {
  733.                         sprintf_s(Message, "IInArchive::Open() failed: hr=0x%.08X.", hr);
  734.                     }
  735.                     ArchiveOpenCallback->Release();
  736.                     ArchiveOpenCallback = NULL;
  737.                 }
  738.                 else
  739.                 {
  740.                     sprintf_s(Message, "CArchiveOpenCallback::Create() failed: hr=0x%.08X.", hr);
  741.                 }
  742.                 InArchive->Release();
  743.                 InArchive = NULL;
  744.             }
  745.             else
  746.             {
  747.                 sprintf_s(Message, "CreateObject() failed: hr=0x%.08X.", hr);
  748.             }
  749.             InStream->Release();
  750.             InStream = NULL;
  751.         }
  752.         else
  753.         {
  754.             sprintf_s(Message, "CInStream::Create() failed: hr=0x%.08X.", hr);
  755.         }
  756.         if (!SUCCEEDED(hr))
  757.         {
  758.             throw std::exception(Message);
  759.         }
  760.     }
  761.     void Update(const std::wstring& FilePath, const std::vector<std::pair<std::wstring, std::wstring>>& FileList)
  762.     {
  763.         if (!m_CreateObject)
  764.         {
  765.             throw std::exception("Not initialized.");
  766.         }
  767.         char Message[512];
  768.         ISequentialOutStream* OutStream = NULL;
  769.         HRESULT hr = COutStream::Create(FilePath, IID_ISequentialOutStream, (void**)&OutStream);
  770.         if (SUCCEEDED(hr))
  771.         {
  772.             IOutArchive* OutArchive = NULL;
  773.             HRESULT hr = m_CreateObject(&ZipHandlerClassId, &IID_IOutArchive, (void**)&OutArchive);
  774.             if (SUCCEEDED(hr))
  775.             {
  776.                 // TODO: encryption
  777.                 //ISetProperties* Properties = NULL;
  778.                 //hr = OutArchive->QueryInterface(IID_ISetProperties, (void**)&Properties);
  779.                 //if (Properties)
  780.                 //{
  781.                 //    // TODO: he=on (header encryption is only available for 7z archives)
  782.                 //    const wchar_t* Name = L"em";
  783.                 //    PROPVARIANT Value;
  784.                 //    PropVariantInit(&Value);
  785.                 //    V_VT(&Value) = VT_BSTR;
  786.                 //    V_BSTR(&Value) = SysAllocString(L"aes256");
  787.                 //    hr = Properties->SetProperties(&Name, &Value, 1);
  788.                 //    PropVariantClear(&Value);
  789.                 //    Properties->Release();
  790.                 //    Properties = NULL;
  791.                 //}
  792.                 IArchiveUpdateCallback* ArchiveUpdateCallback = NULL;
  793.                 hr = CArchiveUpdateCallback::Create(FileList, IID_IArchiveUpdateCallback, (void**)&ArchiveUpdateCallback);
  794.                 if (SUCCEEDED(hr))
  795.                 {
  796.                     hr = OutArchive->UpdateItems(OutStream, static_cast<UInt32>(FileList.size()), ArchiveUpdateCallback);
  797.                     if (!SUCCEEDED(hr))
  798.                     {
  799.                         sprintf_s(Message, "IOutArchive::UpdateItems() failed: hr=0x%.08X.", hr);
  800.                     }
  801.                 }
  802.                 else
  803.                 {
  804.                     sprintf_s(Message, "CArchiveUpdateCallback_Create() failed: hr=0x%.08X.", hr);
  805.                 }
  806.                 OutArchive->Release();
  807.                 OutArchive = NULL;
  808.             }
  809.             else
  810.             {
  811.                 sprintf_s(Message, "CreateObject() failed: hr=0x%.08X.", hr);
  812.             }
  813.             OutStream->Release();
  814.             OutStream = NULL;
  815.         }
  816.         else
  817.         {
  818.             sprintf_s(Message, "COutStream::Create() failed: hr=0x%.08X.", hr);
  819.         }
  820.         if (!SUCCEEDED(hr))
  821.         {
  822.             throw std::exception(Message);
  823.         }
  824.     }
  825. protected:
  826.     std::wstring m_FilePath;
  827.     HMODULE m_ModuleHandle;
  828.     Func_CreateObject m_CreateObject;
  829. };
  830.  
  831. void Utils::ZipUpdate(const std::wstring& FilePath, const std::vector<std::pair<std::wstring, std::wstring>>& FileList)
  832. {
  833.     SevenZip Zip(L"7Z.DLL");
  834.     Zip.Update(FilePath, FileList);
  835. }
  836.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement