diff --git a/.gitignore b/.gitignore index e9aaa394..a8f98d4c 100644 --- a/.gitignore +++ b/.gitignore @@ -397,7 +397,7 @@ __pycache__/ # run git update-index --assume-unchanged lib/zlib/zconf.h lib/zlib # Files generated by CMake -src/inc/MSIXResource.hpp +src/inc/internal/MSIXResource.hpp src/msix/MSIXResource.cpp src/msix/common/MSIXResource.cpp diff --git a/cmake/msix_resources.cmake b/cmake/msix_resources.cmake index 24e473a2..08f29077 100644 --- a/cmake/msix_resources.cmake +++ b/cmake/msix_resources.cmake @@ -348,5 +348,5 @@ foreach(FILE ${RESOURCES_CERTS}) string(APPEND CERTS_HPP result.push_back(std::make_pair(\"${FILE}\", std::move(factory->GetResource(\"${FILE}\")))) ";\n\t\t\t\t") endforeach() -configure_file(${MSIX_PROJECT_ROOT}/src/inc/MSIXResource.hpp.cmakein ${MSIX_PROJECT_ROOT}/src/inc/MSIXResource.hpp CRLF) +configure_file(${MSIX_PROJECT_ROOT}/src/inc/internal/MSIXResource.hpp.cmakein ${MSIX_PROJECT_ROOT}/src/inc/internal/MSIXResource.hpp CRLF) configure_file(${MSIX_PROJECT_ROOT}/src/msix/common/MSIXResource.cpp.cmakein ${MSIX_PROJECT_ROOT}/src/msix/common/MSIXResource.cpp CRLF) diff --git a/pipelines/azure-pipelines-windows.yml b/pipelines/azure-pipelines-windows.yml index 78557298..04c60c3d 100644 --- a/pipelines/azure-pipelines-windows.yml +++ b/pipelines/azure-pipelines-windows.yml @@ -73,8 +73,8 @@ jobs: _arguments: x86 -d --pack _artifact: WIN32chk-pack debug_64_pack: - _arguments: x86 -d --pack - _artifact: WIN32chk-pack + _arguments: x64 -d --pack + _artifact: WIN32-x64chk-pack steps: - task: BatchScript@1 diff --git a/src/inc/Applicability.hpp b/src/inc/internal/Applicability.hpp similarity index 100% rename from src/inc/Applicability.hpp rename to src/inc/internal/Applicability.hpp diff --git a/src/inc/AppxBlockMapObject.hpp b/src/inc/internal/AppxBlockMapObject.hpp similarity index 100% rename from src/inc/AppxBlockMapObject.hpp rename to src/inc/internal/AppxBlockMapObject.hpp diff --git a/src/inc/AppxBlockMapWriter.hpp b/src/inc/internal/AppxBlockMapWriter.hpp similarity index 100% rename from src/inc/AppxBlockMapWriter.hpp rename to src/inc/internal/AppxBlockMapWriter.hpp diff --git a/src/inc/AppxBundleManifest.hpp b/src/inc/internal/AppxBundleManifest.hpp similarity index 100% rename from src/inc/AppxBundleManifest.hpp rename to src/inc/internal/AppxBundleManifest.hpp diff --git a/src/inc/AppxFactory.hpp b/src/inc/internal/AppxFactory.hpp similarity index 100% rename from src/inc/AppxFactory.hpp rename to src/inc/internal/AppxFactory.hpp diff --git a/src/inc/AppxFile.hpp b/src/inc/internal/AppxFile.hpp similarity index 100% rename from src/inc/AppxFile.hpp rename to src/inc/internal/AppxFile.hpp diff --git a/src/inc/AppxManifestObject.hpp b/src/inc/internal/AppxManifestObject.hpp similarity index 100% rename from src/inc/AppxManifestObject.hpp rename to src/inc/internal/AppxManifestObject.hpp diff --git a/src/inc/AppxManifestValidation.hpp b/src/inc/internal/AppxManifestValidation.hpp similarity index 100% rename from src/inc/AppxManifestValidation.hpp rename to src/inc/internal/AppxManifestValidation.hpp diff --git a/src/inc/AppxPackageInfo.hpp b/src/inc/internal/AppxPackageInfo.hpp similarity index 100% rename from src/inc/AppxPackageInfo.hpp rename to src/inc/internal/AppxPackageInfo.hpp diff --git a/src/inc/AppxPackageObject.hpp b/src/inc/internal/AppxPackageObject.hpp similarity index 100% rename from src/inc/AppxPackageObject.hpp rename to src/inc/internal/AppxPackageObject.hpp diff --git a/src/inc/AppxPackageWriter.hpp b/src/inc/internal/AppxPackageWriter.hpp similarity index 100% rename from src/inc/AppxPackageWriter.hpp rename to src/inc/internal/AppxPackageWriter.hpp diff --git a/src/inc/AppxSignature.hpp b/src/inc/internal/AppxSignature.hpp similarity index 100% rename from src/inc/AppxSignature.hpp rename to src/inc/internal/AppxSignature.hpp diff --git a/src/inc/BlockMapStream.hpp b/src/inc/internal/BlockMapStream.hpp similarity index 100% rename from src/inc/BlockMapStream.hpp rename to src/inc/internal/BlockMapStream.hpp diff --git a/src/inc/ContentType.hpp b/src/inc/internal/ContentType.hpp similarity index 100% rename from src/inc/ContentType.hpp rename to src/inc/internal/ContentType.hpp diff --git a/src/inc/ContentTypeWriter.hpp b/src/inc/internal/ContentTypeWriter.hpp similarity index 100% rename from src/inc/ContentTypeWriter.hpp rename to src/inc/internal/ContentTypeWriter.hpp diff --git a/src/inc/Crypto.hpp b/src/inc/internal/Crypto.hpp similarity index 100% rename from src/inc/Crypto.hpp rename to src/inc/internal/Crypto.hpp diff --git a/src/inc/DeflateStream.hpp b/src/inc/internal/DeflateStream.hpp similarity index 100% rename from src/inc/DeflateStream.hpp rename to src/inc/internal/DeflateStream.hpp diff --git a/src/inc/DirectoryObject.hpp b/src/inc/internal/DirectoryObject.hpp similarity index 100% rename from src/inc/DirectoryObject.hpp rename to src/inc/internal/DirectoryObject.hpp diff --git a/src/inc/Encoding.hpp b/src/inc/internal/Encoding.hpp similarity index 100% rename from src/inc/Encoding.hpp rename to src/inc/internal/Encoding.hpp diff --git a/src/inc/Enumerators.hpp b/src/inc/internal/Enumerators.hpp similarity index 100% rename from src/inc/Enumerators.hpp rename to src/inc/internal/Enumerators.hpp diff --git a/src/inc/FileNameValidation.hpp b/src/inc/internal/FileNameValidation.hpp similarity index 100% rename from src/inc/FileNameValidation.hpp rename to src/inc/internal/FileNameValidation.hpp diff --git a/src/inc/FileStream.hpp b/src/inc/internal/FileStream.hpp similarity index 100% rename from src/inc/FileStream.hpp rename to src/inc/internal/FileStream.hpp diff --git a/src/inc/HashStream.hpp b/src/inc/internal/HashStream.hpp similarity index 100% rename from src/inc/HashStream.hpp rename to src/inc/internal/HashStream.hpp diff --git a/src/inc/ICompressionObject.hpp b/src/inc/internal/ICompressionObject.hpp similarity index 100% rename from src/inc/ICompressionObject.hpp rename to src/inc/internal/ICompressionObject.hpp diff --git a/src/inc/IXml.hpp b/src/inc/internal/IXml.hpp similarity index 81% rename from src/inc/IXml.hpp rename to src/inc/internal/IXml.hpp index c74541e1..49504e5c 100644 --- a/src/inc/IXml.hpp +++ b/src/inc/internal/IXml.hpp @@ -194,13 +194,58 @@ MSIX_INTERFACE(IXmlFactory, 0xf82a60ec,0xfbfc,0x4cb9,0xbc,0x04,0x1a,0x0f,0xe2,0x namespace MSIX { MSIX::ComPtr CreateXmlFactory(IMsixFactory* factory); + template + struct StringToNumber + { + static uint32_t Get(const std::string&) + { + static_assert(False::value, "An appropriate specialization must be specified"); + } + }; + + template <> + struct StringToNumber + { + static uint32_t Get(const std::string& str) + { + return static_cast(std::stoul(str)); + } + }; + + template <> + struct StringToNumber + { + static uint64_t Get(const std::string& str) + { + return static_cast(std::stoull(str)); + } + }; + template static T GetNumber(const ComPtr& element, XmlAttributeName attribute, T defaultValue) { const auto& attributeValue = element->GetAttributeValue(attribute); bool hasValue = !attributeValue.empty(); T value = defaultValue; - if (hasValue) { value = static_cast(std::stoul(attributeValue)); } + if (hasValue) + { + try + { + value = StringToNumber::Get(attributeValue); + } + catch (std::invalid_argument& ia) + { + ThrowErrorAndLog(Error::XmlInvalidData, ia.what()); + } + catch (std::out_of_range& oor) + { + ThrowErrorAndLog(Error::XmlInvalidData, oor.what()); + } + catch (...) + { + ThrowErrorAndLog(Error::XmlInvalidData, "Unexpected exception converting string to number"); + } + } return value; } diff --git a/src/inc/InflateStream.hpp b/src/inc/internal/InflateStream.hpp similarity index 100% rename from src/inc/InflateStream.hpp rename to src/inc/internal/InflateStream.hpp diff --git a/src/inc/Log.hpp b/src/inc/internal/Log.hpp similarity index 100% rename from src/inc/Log.hpp rename to src/inc/internal/Log.hpp diff --git a/src/inc/MSIXFactory.hpp b/src/inc/internal/MSIXFactory.hpp similarity index 100% rename from src/inc/MSIXFactory.hpp rename to src/inc/internal/MSIXFactory.hpp diff --git a/src/inc/MSIXResource.hpp.cmakein b/src/inc/internal/MSIXResource.hpp.cmakein similarity index 100% rename from src/inc/MSIXResource.hpp.cmakein rename to src/inc/internal/MSIXResource.hpp.cmakein diff --git a/src/inc/MsixFeatureSelector.hpp b/src/inc/internal/MsixFeatureSelector.hpp similarity index 100% rename from src/inc/MsixFeatureSelector.hpp rename to src/inc/internal/MsixFeatureSelector.hpp diff --git a/src/inc/ObjectBase.hpp b/src/inc/internal/ObjectBase.hpp similarity index 100% rename from src/inc/ObjectBase.hpp rename to src/inc/internal/ObjectBase.hpp diff --git a/src/inc/internal/README.txt b/src/inc/internal/README.txt new file mode 100644 index 00000000..0774b6a2 --- /dev/null +++ b/src/inc/internal/README.txt @@ -0,0 +1 @@ +Contains headers for consumption by both the product and *unit* tests. \ No newline at end of file diff --git a/src/inc/RangeStream.hpp b/src/inc/internal/RangeStream.hpp similarity index 100% rename from src/inc/RangeStream.hpp rename to src/inc/internal/RangeStream.hpp diff --git a/src/inc/ScopeExit.hpp b/src/inc/internal/ScopeExit.hpp similarity index 100% rename from src/inc/ScopeExit.hpp rename to src/inc/internal/ScopeExit.hpp diff --git a/src/inc/SignatureValidator.hpp b/src/inc/internal/SignatureValidator.hpp similarity index 100% rename from src/inc/SignatureValidator.hpp rename to src/inc/internal/SignatureValidator.hpp diff --git a/src/inc/StorageObject.hpp b/src/inc/internal/StorageObject.hpp similarity index 100% rename from src/inc/StorageObject.hpp rename to src/inc/internal/StorageObject.hpp diff --git a/src/inc/StreamHelper.hpp b/src/inc/internal/StreamHelper.hpp similarity index 100% rename from src/inc/StreamHelper.hpp rename to src/inc/internal/StreamHelper.hpp diff --git a/src/inc/StringHelper.hpp b/src/inc/internal/StringHelper.hpp similarity index 100% rename from src/inc/StringHelper.hpp rename to src/inc/internal/StringHelper.hpp diff --git a/src/inc/StringStream.hpp b/src/inc/internal/StringStream.hpp similarity index 100% rename from src/inc/StringStream.hpp rename to src/inc/internal/StringStream.hpp diff --git a/src/inc/UnicodeConversion.hpp b/src/inc/internal/UnicodeConversion.hpp similarity index 100% rename from src/inc/UnicodeConversion.hpp rename to src/inc/internal/UnicodeConversion.hpp diff --git a/src/inc/VectorStream.hpp b/src/inc/internal/VectorStream.hpp similarity index 100% rename from src/inc/VectorStream.hpp rename to src/inc/internal/VectorStream.hpp diff --git a/src/inc/VerifierObject.hpp b/src/inc/internal/VerifierObject.hpp similarity index 100% rename from src/inc/VerifierObject.hpp rename to src/inc/internal/VerifierObject.hpp diff --git a/src/inc/XmlWriter.hpp b/src/inc/internal/XmlWriter.hpp similarity index 100% rename from src/inc/XmlWriter.hpp rename to src/inc/internal/XmlWriter.hpp diff --git a/src/inc/ZipFileStream.hpp b/src/inc/internal/ZipFileStream.hpp similarity index 100% rename from src/inc/ZipFileStream.hpp rename to src/inc/internal/ZipFileStream.hpp diff --git a/src/inc/ZipObject.hpp b/src/inc/internal/ZipObject.hpp similarity index 100% rename from src/inc/ZipObject.hpp rename to src/inc/internal/ZipObject.hpp diff --git a/src/inc/ZipObjectReader.hpp b/src/inc/internal/ZipObjectReader.hpp similarity index 100% rename from src/inc/ZipObjectReader.hpp rename to src/inc/internal/ZipObjectReader.hpp diff --git a/src/inc/ZipObjectWriter.hpp b/src/inc/internal/ZipObjectWriter.hpp similarity index 100% rename from src/inc/ZipObjectWriter.hpp rename to src/inc/internal/ZipObjectWriter.hpp diff --git a/src/inc/AppxPackaging.hpp b/src/inc/public/AppxPackaging.hpp similarity index 100% rename from src/inc/AppxPackaging.hpp rename to src/inc/public/AppxPackaging.hpp diff --git a/src/inc/MSIXWindows.hpp b/src/inc/public/MSIXWindows.hpp similarity index 100% rename from src/inc/MSIXWindows.hpp rename to src/inc/public/MSIXWindows.hpp diff --git a/src/inc/MsixErrors.hpp b/src/inc/public/MsixErrors.hpp similarity index 94% rename from src/inc/MsixErrors.hpp rename to src/inc/public/MsixErrors.hpp index 7223f75f..59902444 100644 --- a/src/inc/MsixErrors.hpp +++ b/src/inc/public/MsixErrors.hpp @@ -3,6 +3,8 @@ // See LICENSE file in the project root for full license information. // #pragma once +#ifndef MSIX_MSIX_ERRORS__H +#define MSIX_MSIX_ERRORS__H namespace MSIX { @@ -84,5 +86,8 @@ namespace MSIX { XmlWarning = XML_FACILITY + 0x0001, XmlError = XML_FACILITY + 0x0002, XmlFatal = XML_FACILITY + 0x0003, + XmlInvalidData = XML_FACILITY + 0x0004, }; } + +#endif diff --git a/src/inc/public/README.txt b/src/inc/public/README.txt new file mode 100644 index 00000000..0c93c174 --- /dev/null +++ b/src/inc/public/README.txt @@ -0,0 +1 @@ +Contains headers for public consumption; can only reference each other and external dependencies. \ No newline at end of file diff --git a/src/inc/ComHelper.hpp b/src/inc/shared/ComHelper.hpp similarity index 100% rename from src/inc/ComHelper.hpp rename to src/inc/shared/ComHelper.hpp diff --git a/src/inc/Exceptions.hpp b/src/inc/shared/Exceptions.hpp similarity index 94% rename from src/inc/Exceptions.hpp rename to src/inc/shared/Exceptions.hpp index 1b48d4d1..0888006d 100644 --- a/src/inc/Exceptions.hpp +++ b/src/inc/shared/Exceptions.hpp @@ -11,10 +11,21 @@ #include #include -#include "Log.hpp" #include "MSIXWindows.hpp" #include "MsixErrors.hpp" +#ifndef MSIX_TEST +#include "Log.hpp" +#else +namespace MSIX { + namespace Global { + namespace Log { + inline void Append(const std::string&) {} + } + } +} +#endif + namespace MSIX { // Defines a common exception type to throw in exceptional cases. DO NOT USE FOR FLOW CONTROL! @@ -122,7 +133,11 @@ namespace MSIX { #define ThrowErrorIf(c, a, m) ThrowErrorIfNot(c,!(a), m) #define ThrowErrorAndLog(c, m) { MSIX::RaiseException(__LINE__, __FILE__, m, c); } +#ifndef MSIX_TEST #define ThrowHrIfFailed(a) MSIX::RaiseExceptionIfFailed(a, __LINE__, __FILE__); +#else +#define ThrowHrIfFailed(a) { HRESULT __excMacroHR = (a); ThrowErrorIf(__excMacroHR, FAILED(__excMacroHR), nullptr) } +#endif #ifdef WIN32 #define ThrowHrIfFalse(a, m) \ diff --git a/src/inc/shared/README.txt b/src/inc/shared/README.txt new file mode 100644 index 00000000..32c0b337 --- /dev/null +++ b/src/inc/shared/README.txt @@ -0,0 +1,3 @@ +Contains headers for consumption by both the product and *functional* tests; can only reference each other, public headers, and external dependencies. + +Any functions used by tests must be implemented in the headers, as the tests will not be linking in anything. \ No newline at end of file diff --git a/src/inc/StreamBase.hpp b/src/inc/shared/StreamBase.hpp similarity index 100% rename from src/inc/StreamBase.hpp rename to src/inc/shared/StreamBase.hpp diff --git a/src/msix/CMakeLists.txt b/src/msix/CMakeLists.txt index 75d3afdf..f82dbad8 100644 --- a/src/msix/CMakeLists.txt +++ b/src/msix/CMakeLists.txt @@ -87,9 +87,9 @@ endif() include(msix_resources) # Handles all the certificates and schemas we are going to use. set(LIB_PUBLIC_HEADERS - ../inc/AppxPackaging.hpp - ../inc/MSIXWindows.hpp - ../inc/MsixErrors.hpp + ../inc/public/AppxPackaging.hpp + ../inc/public/MSIXWindows.hpp + ../inc/public/MsixErrors.hpp ) set(MsixSrc) # list with all the files we are going to use @@ -230,13 +230,13 @@ add_library(${PROJECT_NAME} SHARED add_dependencies(${PROJECT_NAME} LIBS) # Copy out public headers to /src/unpack -configure_file(../inc/MSIXWindows.hpp ${CMAKE_CURRENT_BINARY_DIR}/MSIXWindows.hpp ) -configure_file(../inc/AppxPackaging.hpp ${CMAKE_CURRENT_BINARY_DIR}/AppxPackaging.hpp) -configure_file(../inc/MsixErrors.hpp ${CMAKE_CURRENT_BINARY_DIR}/MsixErrors.hpp) +configure_file(../inc/public/MSIXWindows.hpp ${CMAKE_CURRENT_BINARY_DIR}/MSIXWindows.hpp ) +configure_file(../inc/public/AppxPackaging.hpp ${CMAKE_CURRENT_BINARY_DIR}/AppxPackaging.hpp) +configure_file(../inc/public/MsixErrors.hpp ${CMAKE_CURRENT_BINARY_DIR}/MsixErrors.hpp) # Linker and includes # Include MSIX headers -target_include_directories(${PROJECT_NAME} PRIVATE ${MSIX_PROJECT_ROOT}/src/inc) +target_include_directories(${PROJECT_NAME} PRIVATE ${MSIX_PROJECT_ROOT}/src/inc/public ${MSIX_PROJECT_ROOT}/src/inc/shared ${MSIX_PROJECT_ROOT}/src/inc/internal) if(WIN32) string(REPLACE "/GR" " " CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") diff --git a/src/msix/pack/AppxPackageWriter.cpp b/src/msix/pack/AppxPackageWriter.cpp index 2f44c31c..0338dc9f 100644 --- a/src/msix/pack/AppxPackageWriter.cpp +++ b/src/msix/pack/AppxPackageWriter.cpp @@ -175,7 +175,7 @@ namespace MSIX { ULARGE_INTEGER end = { 0 }; ThrowHrIfFailed(stream->Seek(start, StreamBase::Reference::END, &end)); ThrowHrIfFailed(stream->Seek(start, StreamBase::Reference::START, nullptr)); - std::uint64_t uncompressedSize = static_cast(end.u.LowPart); + std::uint64_t uncompressedSize = static_cast(end.QuadPart); std::string opcFileName; // Don't encode [Content Type].xml diff --git a/src/test/msixtest/CMakeLists.txt b/src/test/msixtest/CMakeLists.txt index ad80ee81..e5bb75df 100644 --- a/src/test/msixtest/CMakeLists.txt +++ b/src/test/msixtest/CMakeLists.txt @@ -14,6 +14,10 @@ if(WIN32) endif() endif() +# Enable differentiation of based on being used in the tests. +# Keep usage of this to a minimum; it is primarily intended for Exceptions.hpp +add_definitions(-DMSIX_TEST=1) + set(MsixTestFiles) list(APPEND MsixTestFiles @@ -81,7 +85,7 @@ else() ) endif() -target_include_directories(${PROJECT_NAME} PRIVATE ${MSIX_BINARY_ROOT}/src/msix ${MSIX_PROJECT_ROOT}/lib/catch2 ${CMAKE_CURRENT_SOURCE_DIR}/inc) +target_include_directories(${PROJECT_NAME} PRIVATE ${MSIX_PROJECT_ROOT}/src/inc/public ${MSIX_PROJECT_ROOT}/lib/catch2 ${CMAKE_CURRENT_SOURCE_DIR}/inc ${MSIX_PROJECT_ROOT}/src/inc/shared) # Output test binaries into a test directory set_target_properties(${PROJECT_NAME} PROPERTIES diff --git a/src/test/msixtest/api_packagewriter.cpp b/src/test/msixtest/api_packagewriter.cpp index 8bae6d74..e5f5abc7 100644 --- a/src/test/msixtest/api_packagewriter.cpp +++ b/src/test/msixtest/api_packagewriter.cpp @@ -8,6 +8,7 @@ #include "FileHelpers.hpp" #include "PackTestData.hpp" #include "macros.hpp" +#include "StreamBase.hpp" #include @@ -350,3 +351,97 @@ TEST_CASE("Api_AppxPackageWriter_closed", "[api]") APPX_COMPRESSION_OPTION_NORMAL, fileStream.Get())); } + +class GeneratedEasilyCompressedFileStream final : public MSIX::StreamBase +{ +public: + GeneratedEasilyCompressedFileStream(uint64_t size) : m_size(size) {} + + // IStream + HRESULT STDMETHODCALLTYPE Seek(LARGE_INTEGER move, DWORD origin, ULARGE_INTEGER* newPosition) noexcept override try + { + // Determine new range relative position + LARGE_INTEGER newPos = { 0 }; + switch (origin) + { + case Reference::CURRENT: + newPos.QuadPart = m_offset + move.QuadPart; + break; + case Reference::START: + newPos.QuadPart = move.QuadPart; + break; + case Reference::END: + newPos.QuadPart = m_size + move.QuadPart; + break; + } + + // Constrain newPos to range relative values + if (newPos.QuadPart < 0) + { + m_offset = 0; + } + else + { + m_offset = std::min(static_cast(newPos.QuadPart), m_size); + } + + if (newPosition) { newPosition->QuadPart = m_offset; } + return static_cast(MSIX::Error::OK); + } CATCH_RETURN(); + + HRESULT STDMETHODCALLTYPE Read(void* buffer, ULONG countBytes, ULONG* bytesRead) noexcept override try + { + uint64_t bytesToRead = std::min(m_size - m_offset, static_cast(countBytes)); + // We can't really fail so just put the value in directly. + if (bytesRead) { *bytesRead = static_cast(bytesToRead); } + + while (bytesToRead) + { + uint64_t block = m_offset / DefaultBlockSize; + uint64_t endOfBlock = (block + 1) * DefaultBlockSize; + uint64_t bytesToWrite = std::min(endOfBlock, m_size) - m_offset; + bytesToWrite = std::min(bytesToWrite, bytesToRead); + memset(buffer, static_cast(block % 256), static_cast(bytesToWrite)); + + buffer = static_cast(static_cast(buffer) + bytesToWrite); + m_offset += bytesToWrite; + bytesToRead -= bytesToWrite; + } + + return static_cast(MSIX::Error::OK); + } CATCH_RETURN(); + +protected: + uint64_t m_size = 0; + uint64_t m_offset = 0; +}; + +// Test creating a valid msix package with a contained file that is larger than 4GB +// The package itself will be much smaller; do not unpack the package from this test +TEST_CASE("Api_AppxPackageWriter_file_over_4GB", "[api][.slow]") +{ + auto outputStream = MsixTest::StreamFile("test_package.msix", false, true); + + MsixTest::ComPtr packageWriter; + InitializePackageWriter(outputStream.Get(), &packageWriter); + + // Create stream to generate our very compressable data with more than 4GB of data + auto fileStream = MsixTest::ComPtr::Make(0x100000100); + REQUIRE_SUCCEEDED(packageWriter->AddPayloadFile( + L"largefile.bin", + TestConstants::ContentType.c_str(), + APPX_COMPRESSION_OPTION_NORMAL, + fileStream.Get())); + + // Finalize package, create manifest stream + MsixTest::ComPtr manifestStream; + MakeManifestStream(&manifestStream); + REQUIRE_SUCCEEDED(packageWriter->Close(manifestStream.Get())); + + // Reopen the package, validates that the written package is readable + // return to the beginning + LARGE_INTEGER zero = { 0 }; + REQUIRE_SUCCEEDED(outputStream.Get()->Seek(zero, STREAM_SEEK_SET, nullptr)); + MsixTest::ComPtr packageReader; + MsixTest::InitializePackageReader(outputStream.Get(), &packageReader); +} diff --git a/src/test/msixtest/inc/msixtest_int.hpp b/src/test/msixtest/inc/msixtest_int.hpp index 21a12204..b11e900a 100644 --- a/src/test/msixtest/inc/msixtest_int.hpp +++ b/src/test/msixtest/inc/msixtest_int.hpp @@ -6,6 +6,7 @@ #include "AppxPackaging.hpp" #include "MSIXWindows.hpp" #include "MsixErrors.hpp" +#include "ComHelper.hpp" #include "msixtest.hpp" #include "macros.hpp" @@ -116,72 +117,8 @@ namespace MsixTest { void InitializeBundleReader(const std::string& package, IAppxBundleReader** bundleReader); void InitializeManifestReader(const std::string& manifest, IAppxManifestReader** manifestReader); - template - class ComPtr - { - public: - // default ctor - ComPtr() = default; - explicit ComPtr(T* ptr) : m_ptr(ptr) { InternalAddRef(); } - - ComPtr(const ComPtr& other) : m_ptr(other.m_ptr) { InternalAddRef(); } - ComPtr& operator=(const ComPtr& other) { InternalRelease(); m_ptr = other.m_ptr; InternalAddRef(); return *this; } - - ComPtr(ComPtr&& other) : m_ptr(other.m_ptr) { other.m_ptr = nullptr; } - ComPtr& operator=(ComPtr&& other) { InternalRelease(); m_ptr = other.m_ptr; other.m_ptr = nullptr; return *this; } - - ~ComPtr() { InternalRelease(); } - - // For use instead of ComPtr t(new Foo(...)); - template - static ComPtr Make(Args&&... args) - { - ComPtr result; - result.m_ptr = new U(std::forward(args)...); - return result; - } - - inline T* operator->() const { return m_ptr; } - inline T* Get() const { return m_ptr; } - T* Detach() - { - T* temp = m_ptr; - m_ptr = nullptr; - return temp; - } - - template - ComPtr As() const - { - ComPtr out; - REQUIRE_SUCCEEDED(m_ptr->QueryInterface(UuidOfImpl::iid, reinterpret_cast(&out))); - return out; - } - - inline T** operator&() - { InternalRelease(); - return &m_ptr; - } - - bool Release() - { - return InternalRelease(); - } - - protected: - T* m_ptr = nullptr; - - inline void InternalAddRef() { if (m_ptr) { m_ptr->AddRef(); } } - inline bool InternalRelease() - { - T* temp = m_ptr; - if (temp) - { m_ptr = nullptr; - return (temp->Release() == 0); - } - return false; - } - }; + // Use the product ComPtr; enables sharing without updating every qualified use. + using MSIX::ComPtr; // Helper class that creates a stream from a given file name. // toRead - true if the file already exists, false to create it diff --git a/src/test/msixtest/msixtest.cpp b/src/test/msixtest/msixtest.cpp index 3bc43012..767965ec 100644 --- a/src/test/msixtest/msixtest.cpp +++ b/src/test/msixtest/msixtest.cpp @@ -215,12 +215,10 @@ namespace MsixTest { { if (m_toDelete && (m_stream.Get() != nullptr)) { + m_stream = nullptr; // best effort to delete the file. If someone else has a reference to this stream // and this object is deleted, the file WILL NOT be deleted. - if (m_stream.Release()) - { - remove(m_fileName.c_str()); - } + remove(m_fileName.c_str()); } } }