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 }