winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

Archive.cpp (3377B)


      1 // Copyright (c) Microsoft Corporation.
      2 // Licensed under the MIT License.
      3 #include "pch.h"
      4 #include "Public/winget/Archive.h"
      5 
      6 // TODO: Move include statement to pch.h and resolve build errors
      7 #pragma warning( push )
      8 #pragma warning ( disable : 4189 4244 26451 )
      9 #include <pure.h>
     10 #pragma warning ( pop )
     11 
     12 namespace AppInstaller::Archive
     13 {
     14     using unique_pidlist_absolute = wil::unique_any<PIDLIST_ABSOLUTE, decltype(&::CoTaskMemFree), ::CoTaskMemFree>;
     15     using unique_lpitemidlist = wil::unique_any<LPITEMIDLIST, decltype(&::CoTaskMemFree), ::CoTaskMemFree>;
     16 
     17     HRESULT TryExtractArchive(const std::filesystem::path& archivePath, const std::filesystem::path& destPath)
     18     {
     19         wil::com_ptr<IFileOperation> pFileOperation;
     20         RETURN_IF_FAILED(CoCreateInstance(CLSID_FileOperation, NULL, CLSCTX_ALL, IID_PPV_ARGS(&pFileOperation)));
     21         RETURN_IF_FAILED(pFileOperation->SetOperationFlags(FOF_NO_UI));
     22 
     23         wil::com_ptr<IShellItem> pShellItemTo;
     24         RETURN_IF_FAILED(SHCreateItemFromParsingName(destPath.c_str(), NULL, IID_PPV_ARGS(&pShellItemTo)));
     25 
     26         unique_pidlist_absolute pidlFull;
     27         RETURN_IF_FAILED(SHParseDisplayName(archivePath.c_str(), NULL, &pidlFull, 0, NULL));
     28 
     29         wil::com_ptr<IShellFolder> pArchiveShellFolder;
     30         RETURN_IF_FAILED(SHBindToObject(NULL, pidlFull.get(), NULL, IID_PPV_ARGS(&pArchiveShellFolder)));
     31 
     32         wil::com_ptr<IEnumIDList> pEnumIdList;
     33         RETURN_IF_FAILED(pArchiveShellFolder->EnumObjects(nullptr, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &pEnumIdList));
     34 
     35         unique_lpitemidlist pidlChild;
     36         ULONG nFetched;
     37         while (pEnumIdList->Next(1, wil::out_param_ptr<LPITEMIDLIST*>(pidlChild), &nFetched) == S_OK && nFetched == 1)
     38         {
     39             wil::com_ptr<IShellItem> pShellItemFrom;
     40             STRRET strFolderName;
     41             WCHAR szFolderName[MAX_PATH];
     42             RETURN_IF_FAILED(pArchiveShellFolder->GetDisplayNameOf(pidlChild.get(), SHGDN_INFOLDER | SHGDN_FORPARSING, &strFolderName));
     43             RETURN_IF_FAILED(StrRetToBuf(&strFolderName, pidlChild.get(), szFolderName, MAX_PATH));
     44             RETURN_IF_FAILED(SHCreateItemWithParent(pidlFull.get(), pArchiveShellFolder.get(), pidlChild.get(), IID_PPV_ARGS(&pShellItemFrom)));
     45             RETURN_IF_FAILED(pFileOperation->CopyItem(pShellItemFrom.get(), pShellItemTo.get(), NULL, NULL));
     46         }
     47 
     48         RETURN_IF_FAILED(pFileOperation->PerformOperations());
     49         return S_OK;
     50     }
     51 
     52 #ifndef AICLI_DISABLE_TEST_HOOKS
     53     static bool* s_ScanArchiveResult_TestHook_Override = nullptr;
     54 
     55     void TestHook_SetScanArchiveResult_Override(bool* status)
     56     {
     57         s_ScanArchiveResult_TestHook_Override = status;
     58     }
     59 #endif
     60 
     61     bool ScanZipFile(const std::filesystem::path& zipPath)
     62     {
     63 #ifndef AICLI_DISABLE_TEST_HOOKS
     64         if (s_ScanArchiveResult_TestHook_Override)
     65         {
     66             return *s_ScanArchiveResult_TestHook_Override;
     67         }
     68 #endif
     69 
     70         std::ifstream instream{ zipPath, std::ios::in | std::ios::binary };
     71         std::vector<uint8_t> data{ { std::istreambuf_iterator<char>{ instream } }, std::istreambuf_iterator<char>{} };
     72 
     73         uint8_t* buffer = &data[0];
     74         uint64_t flag = 0;
     75         int scanResult = pure_zip(buffer, data.size(), flag);
     76 
     77         return scanResult == 0;
     78     }
     79 }