Merged PR 2308191: [MSIX SDK] add a c-make switch to exclude bundles from unpack

Enable the user to disable bundle support for the SDK by specifying -DSKIP_BUNDLES=on on CMake. If the user tries to unpack a bundle or create a bundle factory they will get 0x80070032 (E_NOTSUPPORTED). The binary size decreases ~60k.

Win x64
- bundle: 464 k
- no bundle: 413 k

Win x86
- bundle: 330 k
- no bundle: 293 k

Linux
- bundle: 5,424 k
- no bundle: 5,330 k

AOSP arm
- bundle: 4,381 k
- no bundle: 4,313 k

AOSP arm v7a
- bundle: 4,288 k
- no bundle: 4,220 k

MacOS
- bundle: 4,487 k
- no bundle: 4,413 k

iOS arm64
- bundle: 4,516 k
- no bundle: 4,458 k

Related work items: #18753331
This commit is contained in:
Ruben Guerrero Samaniego 2018-09-06 18:45:34 +00:00 коммит произвёл msftrubengu
Родитель f895380e77
Коммит dea2e72be9
19 изменённых файлов: 547 добавлений и 401 удалений

Просмотреть файл

@ -18,6 +18,7 @@ option(LINUX "Build for Linux" OFF)
option(USE_VALIDATION_PARSER "Turn on to validates using the resouce schemas. Default (OFF) validates XML files are just valid XML" OFF)
option(USE_SHARED_ZLIB "Choose the type of dependency for zlib, Use the -DUSE_SHARED_ZLIB=on to have a shared dependency. Default is 'off' (static)" OFF)
option(USE_STATIC_MSVC "Windows only. Pass /MT as a compiler flag to use the staic version of the run-time library. Default is 'off' (dynamic)" OFF)
option(SKIP_BUNDLES "Removes bundle functionality from the MSIX SDK. Default is 'off'" OFF)
set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel. Use the -DCMAKE_BUILD_TYPE=[option] to specify.")
set(XML_PARSER "" CACHE STRING "Choose the type of parser, options are: [xerces, msxml6]. Use the -DXML_PARSER=[option] to specify.")

Просмотреть файл

@ -8,6 +8,7 @@ version=19
sdk=
sdkver=24
dataCompressionLib=NDK_libz
bundle=off
usage()
{
@ -19,6 +20,7 @@ usage()
echo $'\t' "-arch Architecture ABI. Default x86"
echo $'\t' "-b Build type. Default MinSizeRel"
echo $'\t' "-xzlib Use MSIX SDK Zlib instead of inbox libz.so"
echo $'\t' "-sb Skip bundle support."
}
printsetup()
@ -30,6 +32,7 @@ printsetup()
echo "Architecture:" $arch
echo "Build Type:" $build
echo "Zlib:" $dataCompressionLib
echo "Skip bundle support:" $bundle
}
while [ "$1" != "" ]; do
@ -58,8 +61,10 @@ while [ "$1" != "" ]; do
-sdkver ) shift
sdkver=$1
;;
* ) usage
exit 1
-sb ) bundle="on"
;;
* ) usage
exit 1
esac
shift
done
@ -96,5 +101,5 @@ cmake -DCMAKE_SYSTEM_NAME=Android \
-DCMAKE_ANDROID_ARCH_ABI="$arch" \
-DCMAKE_ANDROID_NDK_TOOLCHAIN_VERSION=clang \
-DCMAKE_ANDROID_STL_TYPE=c++_shared \
-DCMAKE_BUILD_TYPE="$build" $zlib -DAOSP=on ..
-DCMAKE_BUILD_TYPE="$build" $zlib -DSKIP_BUNDLES=$bundle -DAOSP=on ..
make

Просмотреть файл

@ -3,6 +3,7 @@
build=MinSizeRel
arch=x86_64
dataCompressionLib=libcompression
bundle=off
usage()
{
@ -10,6 +11,7 @@ usage()
echo $'\t' "-b Build type. Default MinSizeRel"
echo $'\t' "-arch OSX Architecture. Default x86_64 (simulator)"
echo $'\t' "-xzlib Use MSIX SDK Zlib instead of inbox libCompression api. Default on iOS is libCompression."
echo $'\t' "-sb Skip bundle support."
}
printsetup()
@ -17,6 +19,7 @@ printsetup()
echo "Build Type:" $build
echo "Architecture:" $arch
echo "Data Compression library:" $dataCompressionLib
echo "Skip bundle support:" $bundle
}
while [ "$1" != "" ]; do
@ -30,6 +33,8 @@ while [ "$1" != "" ]; do
-xzlib )dataCompressionLib=MSIX_SDK_zlib
zlib="-DUSE_MSIX_SDK_ZLIB=on"
;;
-sb ) bundle="on"
;;
-h ) usage
exit
;;
@ -46,5 +51,5 @@ cd .vs
# clean up any old builds of msix modules
find . -name *msix* -d | xargs rm -r
cmake -DCMAKE_BUILD_TYPE=$build $zlib -DIOS=on -DCMAKE_TOOLCHAIN_FILE=../cmake/ios.cmake -DCMAKE_OSX_ARCHITECTURES=$arch ..
cmake -DCMAKE_BUILD_TYPE=$build $zlib -DIOS=on -DCMAKE_TOOLCHAIN_FILE=../cmake/ios.cmake -DCMAKE_OSX_ARCHITECTURES=$arch -DSKIP_BUNDLES=$bundle ..
make

Просмотреть файл

@ -1,16 +1,19 @@
#!/bin/bash
# script to build on linux
build=MinSizeRel
bundle=off
usage()
{
echo "usage: makelinux [-b buildType]"
echo "usage: makelinux [-b buildType] [-sb]"
echo $'\t' "-b Build type. Default MinSizeRel"
echo $'\t' "-sb Skip bundle support."
}
printsetup()
{
echo "Build Type:" $build
echo "Skip bundle support:" $bundle
}
while [ "$1" != "" ]; do
@ -21,6 +24,8 @@ while [ "$1" != "" ]; do
-h ) usage
exit
;;
-sb ) bundle="on"
;;
* ) usage
exit 1
esac
@ -34,5 +39,5 @@ cd .vs
# clean up any old builds of msix modules
find . -name *msix* -d | xargs rm -r
cmake -DCMAKE_BUILD_TYPE=$build -DLINUX=on ..
cmake -DCMAKE_BUILD_TYPE=$build -DSKIP_BUNDLES=$bundle -DLINUX=on ..
make

Просмотреть файл

@ -2,18 +2,21 @@
# script to build on mac
build=MinSizeRel
dataCompressionLib=libcompression
bundle=off
usage()
{
echo "usage: makemac [-b buildType] [-xzlib]"
echo $'\t' "-b Build type. Default MinSizeRel"
echo $'\t' "-xzlib Use MSIX SDK Zlib instead of inbox libCompression api. Default on MacOS is libCompression."
echo $'\t' "-sb Skip bundle support."
}
printsetup()
{
echo "Build Type:" $build
echo "Data Compression library:" $dataCompressionLib
echo "Skip bundle support:" $bundle
}
while [ "$1" != "" ]; do
@ -24,6 +27,8 @@ while [ "$1" != "" ]; do
-xzlib )dataCompressionLib=MSIX_SDK_zlib
zlib="-DUSE_MSIX_SDK_ZLIB=on"
;;
-sb ) bundle="on"
;;
-h ) usage
exit
;;
@ -40,5 +45,5 @@ cd .vs
# clean up any old builds of msix modules
find . -name *msix* -d | xargs rm -r
cmake -DCMAKE_BUILD_TYPE=$build $zlib -DMACOS=on ..
cmake -DCMAKE_BUILD_TYPE=$build $zlib -DSKIP_BUNDLES=$bundle -DMACOS=on ..
make

Просмотреть файл

@ -29,6 +29,7 @@ set validationParser="-DUSE_VALIDATION_PARSER=off"
set zlib="-DUSE_SHARED_ZLIB=off"
set parser="-DXML_PARSER=msxml6"
set msvc="-DUSE_STATIC_MSVC=off"
set bundle="-DSKIP_BUNDLES=off"
:parseArgs
if /I "%~2" == "--debug" (
@ -58,6 +59,12 @@ if /I "%~2" == "-sz" (
if /I "%~2" == "-mt" (
set msvc="-DUSE_STATIC_MSVC=on"
)
if /I "%~2" == "--skip-bundles" (
set bundle="-DSKIP_BUNDLES=on"
)
if /I "%~2" == "-sb" (
set bundle="-DSKIP_BUNDLES=on"
)
shift /2
if not "%~2"=="" goto parseArgs
@ -66,8 +73,8 @@ cd .vs
if exist CMakeFiles rd /s /q CMakeFiles
if exist CMakeCache.txt del CMakeCache.txt
echo cmake -DWIN32=on -DCMAKE_BUILD_TYPE=%build% %validationParser% %zlib% %parser% %msvc% -G"NMake Makefiles" ..
cmake -DWIN32=on -DCMAKE_BUILD_TYPE=%build% %validationParser% %zlib% %parser% %msvc% -G"NMake Makefiles" ..
echo cmake -DWIN32=on -DCMAKE_BUILD_TYPE=%build% %validationParser% %zlib% %parser% %msvc% %bundle% -G"NMake Makefiles" ..
cmake -DWIN32=on -DCMAKE_BUILD_TYPE=%build% %validationParser% %zlib% %parser% %msvc% %bundle% -G"NMake Makefiles" ..
nmake
goto Exit
@ -85,6 +92,7 @@ echo --parser-xerces, -px = use Xerces-C parser. Default MSXML6.
echo --validation-parser, -vp = enable XML schema validation.
echo --shared-zlib, -sz = don't statically link zlib.
echo -mt = use compiler flag /MT to use static version of the run-time library.
echo --skip-bundles, -sb = turn off bundle support.
echo --help, -h, /? = print this usage information and exit.
:Exit
EXIT /B 0

Просмотреть файл

@ -28,7 +28,7 @@ add_executable(${BINARY_NAME}
set_property(TARGET ${BINARY_NAME} PROPERTY CXX_STANDARD 14)
ADD_DEPENDENCIES(${BINARY_NAME} msix)
if (LINUX)
if (LINUX OR AOSP)
target_link_libraries(${BINARY_NAME} PRIVATE -latomic)
endif()
target_link_libraries(${BINARY_NAME} PRIVATE msix)

Просмотреть файл

@ -0,0 +1,142 @@
//
// Copyright (C) 2017 Microsoft. All rights reserved.
// See LICENSE file in the project root for full license information.
//
#pragma once
#include <vector>
#include "AppxPackaging.hpp"
#include "MSIXFactory.hpp"
#include "ComHelper.hpp"
#include "Applicability.hpp"
#include "VerifierObject.hpp"
EXTERN_C const IID IID_IBundleInfo;
#ifndef WIN32
// {ff82ffcd-747a-4df9-8879-853ab9dd15a1}
interface IBundleInfo : public IUnknown
#else
#include "Unknwn.h"
#include "Objidl.h"
class IBundleInfo : public IUnknown
#endif
{
public:
virtual std::vector<MSIX::ComPtr<IAppxBundleManifestPackageInfo>>& GetPackages() = 0;
};
EXTERN_C const IID IID_IAppxBundleManifestPackageInfoInternal;
#ifndef WIN32
// {32e6fcf0-729b-401d-9dbc-f927b494f9af}
interface IAppxBundleManifestPackageInfoInternal : public IUnknown
#else
#include "Unknwn.h"
#include "Objidl.h"
class IAppxBundleManifestPackageInfoInternal : public IUnknown
#endif
{
public:
virtual const std::string& GetFileName() = 0;
virtual const std::vector<MSIX::Bcp47Tag>& GetLanguages() = 0;
virtual const std::uint64_t GetOffset() = 0;
virtual bool HasQualifiedResources() = 0;
};
SpecializeUuidOfImpl(IAppxBundleManifestPackageInfoInternal);
SpecializeUuidOfImpl(IBundleInfo);
namespace MSIX {
class AppxBundleManifestObject final : public ComClass<AppxBundleManifestObject, IAppxBundleManifestReader, IVerifierObject, IBundleInfo>
{
public:
AppxBundleManifestObject(IMsixFactory* factory, const ComPtr<IStream>& stream);
// IVerifierObject
bool HasStream() override { return !!m_stream; }
ComPtr<IStream> GetStream() override { return m_stream; }
ComPtr<IStream> GetValidationStream(const std::string& part, const ComPtr<IStream>&) override { NOTSUPPORTED; }
const std::string& GetPublisher() override { NOTSUPPORTED; }
// IAppxBundleManifestReader
HRESULT STDMETHODCALLTYPE GetPackageId(IAppxManifestPackageId **packageId) noexcept override;
HRESULT STDMETHODCALLTYPE GetPackageInfoItems(IAppxBundleManifestPackageInfoEnumerator **packageInfoItems) noexcept override;
HRESULT STDMETHODCALLTYPE GetStream(IStream **manifestStream) noexcept override;
// IBundleInfo
std::vector<ComPtr<IAppxBundleManifestPackageInfo>>& GetPackages() override { return m_packages; }
protected:
IMsixFactory* m_factory;
ComPtr<IStream> m_stream;
ComPtr<IAppxManifestPackageId> m_packageId;
std::vector<ComPtr<IAppxBundleManifestPackageInfo>> m_packages;
};
class AppxBundleQualifiedResource final : public MSIX::ComClass<AppxBundleQualifiedResource, IAppxManifestQualifiedResource>
{
public:
AppxBundleQualifiedResource(IMsixFactory* factory, const std::string& language) : m_factory(factory), m_language(language) {}
// IAppxManifestQualifiedResource
HRESULT STDMETHODCALLTYPE GetLanguage(LPWSTR *language) noexcept override try
{
return m_factory->MarshalOutString(m_language, language);
} CATCH_RETURN();
// For now we don't having other resources other than language
HRESULT STDMETHODCALLTYPE GetScale(UINT32 *scale) noexcept override
{
return static_cast<HRESULT>(Error::NotImplemented);
}
HRESULT STDMETHODCALLTYPE GetDXFeatureLevel(DX_FEATURE_LEVEL *dxFeatureLevel) noexcept override
{
return static_cast<HRESULT>(Error::NotImplemented);
}
protected:
IMsixFactory* m_factory;
std::string m_language;
};
class AppxBundleManifestPackageInfo final : public ComClass<AppxBundleManifestPackageInfo, IAppxBundleManifestPackageInfo, IAppxBundleManifestPackageInfoInternal>
{
public:
AppxBundleManifestPackageInfo(
IMsixFactory* factory,
const std::string& name,
const std::string& bundleName,
const std::string& version,
const std::uint64_t size,
const std::uint64_t offset,
const std::string& resourceId,
const std::string& architecture,
const std::string& publisherId,
std::vector<Bcp47Tag>& languages,
APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE packageType);
// IAppxBundleManifestPackageInfo
HRESULT STDMETHODCALLTYPE GetPackageType(APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE *packageType) noexcept override;
HRESULT STDMETHODCALLTYPE GetPackageId(IAppxManifestPackageId **packageId) noexcept override;
HRESULT STDMETHODCALLTYPE GetFileName(LPWSTR *fileName) noexcept override;
HRESULT STDMETHODCALLTYPE GetOffset(UINT64 *offset) noexcept override;
HRESULT STDMETHODCALLTYPE GetSize(UINT64 *size) noexcept override;
HRESULT STDMETHODCALLTYPE GetResources(IAppxManifestQualifiedResourcesEnumerator **resources) noexcept override;
// IAppxBundleManifestPackageInfoInternal
const std::string& GetFileName() override { return m_fileName; }
const std::vector<Bcp47Tag>& GetLanguages() override { return m_languages; }
const std::uint64_t GetOffset() override { return m_offset; }
bool HasQualifiedResources() override { return !m_languages.empty(); }
private:
IMsixFactory* m_factory;
std::string m_fileName;
ComPtr<IAppxManifestPackageId> m_packageId;
std::uint64_t m_size;
std::uint64_t m_offset;
std::vector<Bcp47Tag> m_languages;
APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE m_packageType = APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE_APPLICATION;
};
}

Просмотреть файл

@ -32,22 +32,8 @@ public:
virtual const MSIX_PLATFORMS GetPlatform() = 0;
};
EXTERN_C const IID IID_IBundleInfo;
#ifndef WIN32
// {ff82ffcd-747a-4df9-8879-853ab9dd15a1}
interface IBundleInfo : public IUnknown
#else
#include "Unknwn.h"
#include "Objidl.h"
class IBundleInfo : public IUnknown
#endif
{
public:
virtual std::vector<MSIX::ComPtr<IAppxBundleManifestPackageInfo>>& GetPackages() = 0;
};
SpecializeUuidOfImpl(IAppxManifestObject);
SpecializeUuidOfImpl(IBundleInfo);
namespace MSIX {
@ -228,30 +214,4 @@ namespace MSIX {
std::vector<ComPtr<IAppxManifestTargetDeviceFamily>> m_tdf;
ComPtr<IXmlDom> m_dom;
};
class AppxBundleManifestObject final : public ComClass<AppxBundleManifestObject, IAppxBundleManifestReader, IVerifierObject, IBundleInfo>
{
public:
AppxBundleManifestObject(IMsixFactory* factory, const ComPtr<IStream>& stream);
// IVerifierObject
bool HasStream() override { return !!m_stream; }
ComPtr<IStream> GetStream() override { return m_stream; }
ComPtr<IStream> GetValidationStream(const std::string& part, const ComPtr<IStream>&) override { NOTSUPPORTED; }
const std::string& GetPublisher() override { NOTSUPPORTED; }
// IAppxBundleManifestReader
HRESULT STDMETHODCALLTYPE GetPackageId(IAppxManifestPackageId **packageId) noexcept override;
HRESULT STDMETHODCALLTYPE GetPackageInfoItems(IAppxBundleManifestPackageInfoEnumerator **packageInfoItems) noexcept override;
HRESULT STDMETHODCALLTYPE GetStream(IStream **manifestStream) noexcept override;
// IBundleInfo
std::vector<ComPtr<IAppxBundleManifestPackageInfo>>& GetPackages() override { return m_packages; }
protected:
IMsixFactory* m_factory;
ComPtr<IStream> m_stream;
ComPtr<IAppxManifestPackageId> m_packageId;
std::vector<ComPtr<IAppxBundleManifestPackageInfo>> m_packages;
};
}

Просмотреть файл

@ -7,10 +7,8 @@
#include "ComHelper.hpp"
#include "MSIXFactory.hpp"
#include "Exceptions.hpp"
#include "Applicability.hpp"
#include <string>
#include <vector>
#include <memory>
EXTERN_C const IID IID_IAppxManifestPackageIdInternal;
@ -33,25 +31,7 @@ public:
virtual const std::string GetPackageFamilyName() = 0;
};
EXTERN_C const IID IID_IAppxBundleManifestPackageInfoInternal;
#ifndef WIN32
// {32e6fcf0-729b-401d-9dbc-f927b494f9af}
interface IAppxBundleManifestPackageInfoInternal : public IUnknown
#else
#include "Unknwn.h"
#include "Objidl.h"
class IAppxBundleManifestPackageInfoInternal : public IUnknown
#endif
{
public:
virtual const std::string& GetFileName() = 0;
virtual const std::vector<MSIX::Bcp47Tag>& GetLanguages() = 0;
virtual const std::uint64_t GetOffset() = 0;
virtual bool HasQualifiedResources() = 0;
};
SpecializeUuidOfImpl(IAppxManifestPackageIdInternal);
SpecializeUuidOfImpl(IAppxBundleManifestPackageInfoInternal);
namespace MSIX {
@ -152,71 +132,4 @@ namespace MSIX {
std::string m_publisherId;
std::string m_publisher;
};
class AppxBundleQualifiedResource final : public MSIX::ComClass<AppxBundleQualifiedResource, IAppxManifestQualifiedResource>
{
public:
AppxBundleQualifiedResource(IMsixFactory* factory, const std::string& language) : m_factory(factory), m_language(language) {}
// IAppxManifestQualifiedResource
HRESULT STDMETHODCALLTYPE GetLanguage(LPWSTR *language) noexcept override try
{
return m_factory->MarshalOutString(m_language, language);
} CATCH_RETURN();
// For now we don't having other resources other than language
HRESULT STDMETHODCALLTYPE GetScale(UINT32 *scale) noexcept override
{
return static_cast<HRESULT>(Error::NotImplemented);
}
HRESULT STDMETHODCALLTYPE GetDXFeatureLevel(DX_FEATURE_LEVEL *dxFeatureLevel) noexcept override
{
return static_cast<HRESULT>(Error::NotImplemented);
}
protected:
IMsixFactory* m_factory;
std::string m_language;
};
class AppxBundleManifestPackageInfo final : public ComClass<AppxBundleManifestPackageInfo, IAppxBundleManifestPackageInfo, IAppxBundleManifestPackageInfoInternal>
{
public:
AppxBundleManifestPackageInfo(
IMsixFactory* factory,
const std::string& name,
const std::string& bundleName,
const std::string& version,
const std::uint64_t size,
const std::uint64_t offset,
const std::string& resourceId,
const std::string& architecture,
const std::string& publisherId,
std::vector<Bcp47Tag>& languages,
APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE packageType);
// IAppxBundleManifestPackageInfo
HRESULT STDMETHODCALLTYPE GetPackageType(APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE *packageType) noexcept override;
HRESULT STDMETHODCALLTYPE GetPackageId(IAppxManifestPackageId **packageId) noexcept override;
HRESULT STDMETHODCALLTYPE GetFileName(LPWSTR *fileName) noexcept override;
HRESULT STDMETHODCALLTYPE GetOffset(UINT64 *offset) noexcept override;
HRESULT STDMETHODCALLTYPE GetSize(UINT64 *size) noexcept override;
HRESULT STDMETHODCALLTYPE GetResources(IAppxManifestQualifiedResourcesEnumerator **resources) noexcept override;
// IAppxBundleManifestPackageInfoInternal
const std::string& GetFileName() override { return m_fileName; }
const std::vector<Bcp47Tag>& GetLanguages() override { return m_languages; }
const std::uint64_t GetOffset() override { return m_offset; }
bool HasQualifiedResources() override { return !m_languages.empty(); }
private:
IMsixFactory* m_factory;
std::string m_fileName;
ComPtr<IAppxManifestPackageId> m_packageId;
std::uint64_t m_size;
std::uint64_t m_offset;
std::vector<Bcp47Tag> m_languages;
APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE m_packageType = APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE_APPLICATION;
};
}

Просмотреть файл

@ -78,12 +78,14 @@ namespace MSIX {
AddRef();
return S_OK;
}
#ifdef BUNDLE_SUPPORT
if (riid == UuidOfImpl<IAppxBundleReader>::iid && m_isBundle)
{
*ppvObject = static_cast<void*>(static_cast<IAppxBundleReader*>(this));
AddRef();
return S_OK;
}
#endif //BUNDLE_SUPPORT
if (riid == UuidOfImpl<IUnknown>::iid)
{
*ppvObject = static_cast<void*>(reinterpret_cast<IUnknown*>(this));

Просмотреть файл

@ -0,0 +1,200 @@
//
// Copyright (C) 2017 Microsoft. All rights reserved.
// See LICENSE file in the project root for full license information.
//
#include "AppxBundleManifest.hpp"
#include "AppxPackageInfo.hpp"
#include "ComHelper.hpp"
#include "Enumerators.hpp"
#include "Encoding.hpp"
#include "IXml.hpp"
#include <regex>
namespace MSIX {
AppxBundleManifestObject::AppxBundleManifestObject(IMsixFactory* factory, const ComPtr<IStream>& stream) : m_factory(factory), m_stream(stream)
{
ComPtr<IXmlFactory> xmlFactory;
ThrowHrIfFailed(m_factory->QueryInterface(UuidOfImpl<IXmlFactory>::iid, reinterpret_cast<void**>(&xmlFactory)));
auto dom = xmlFactory->CreateDomFromStream(XmlContentType::AppxBundleManifestXml, stream);
XmlVisitor visitorIdentity(static_cast<void*>(this), [](void* s, const ComPtr<IXmlElement>& identityNode)->bool
{
AppxBundleManifestObject* self = reinterpret_cast<AppxBundleManifestObject*>(s);
ThrowErrorIf(Error::AppxManifestSemanticError, (nullptr != self->m_packageId.Get()), "There must be only one Identity element at most in AppxBundleManifest.xml");
const auto& name = identityNode->GetAttributeValue(XmlAttributeName::Name);
const auto& publisher = identityNode->GetAttributeValue(XmlAttributeName::Publisher);
const auto& version = identityNode->GetAttributeValue(XmlAttributeName::Version);
ThrowErrorIf(Error::AppxManifestSemanticError, (publisher.empty()), "Invalid Identity element");
// Bundles don't have a ResourceId attribute in their manifest, but is always ~ for the package identity.
self->m_packageId = ComPtr<IAppxManifestPackageId>::Make<AppxManifestPackageId>(self->m_factory, name, version, "~", "neutral", publisher);
return true;
});
dom->ForEachElementIn(dom->GetDocument(), XmlQueryName::Bundle_Identity, visitorIdentity);
struct _context
{
AppxBundleManifestObject* self;
IXmlDom* dom;
std::vector<std::string> packageNames;
size_t mainPackages;
};
_context context = { this, dom.Get(), {} , 0};
XmlVisitor visitorPackages(static_cast<void*>(&context), [](void* c, const ComPtr<IXmlElement>& packageNode)->bool
{
_context* context = reinterpret_cast<_context*>(c);
const auto& name = packageNode->GetAttributeValue(XmlAttributeName::Bundle_Package_FileName);
std::ostringstream builder;
builder << "Duplicate file: '" << name << "' specified in AppxBundleManifest.xml.";
ThrowErrorIf(Error::AppxManifestSemanticError,
std::find(std::begin(context->packageNames), std::end(context->packageNames), name) != context->packageNames.end(),
builder.str().c_str());
context->packageNames.push_back(name);
const auto& version = packageNode->GetAttributeValue(XmlAttributeName::Version);
const auto& resourceId = packageNode->GetAttributeValue(XmlAttributeName::ResourceId);
const auto& architecture = packageNode->GetAttributeValue(XmlAttributeName::Bundle_Package_Architecture);
const auto& type = packageNode->GetAttributeValue(XmlAttributeName::Bundle_Package_Type);
const auto size = GetNumber<std::uint64_t>(packageNode, XmlAttributeName::Size, 0);
const auto offset = GetNumber<std::uint64_t>(packageNode, XmlAttributeName::Bundle_Package_Offset, 0);
// Default value is resource
APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE packageType = (type.empty() || type == "resource") ?
APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE_RESOURCE : APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE_APPLICATION;
struct _resourcesContext
{
std::vector<Bcp47Tag> languages;
bool hasResources;
};
_resourcesContext resourcesContext = { {}, false};
XmlVisitor visitor(static_cast<void*>(&resourcesContext), [](void* c, const ComPtr<IXmlElement>& resourceNode)->bool
{
_resourcesContext* resourcesContext = reinterpret_cast<_resourcesContext*>(c);
const auto& language = resourceNode->GetAttributeValue(XmlAttributeName::Language);
if (!language.empty()) { resourcesContext->languages.push_back(Bcp47Tag(language)); }
resourcesContext->hasResources = true;
return true;
});
context->dom->ForEachElementIn(packageNode, XmlQueryName::Bundle_Packages_Package_Resources_Resource, visitor);
if ((packageType == APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE_RESOURCE) && resourcesContext.languages.empty() && resourcesContext.hasResources)
{ // For now, we only support languages resource packages
return true;
}
ComPtr<IAppxManifestPackageIdInternal> packageIdInternal = context->self->m_packageId.As<IAppxManifestPackageIdInternal>();
auto package = ComPtr<IAppxBundleManifestPackageInfo>::Make<AppxBundleManifestPackageInfo>(
context->self->m_factory, name, packageIdInternal->GetName(), version, size, offset, resourceId,
architecture, packageIdInternal->GetPublisher(), resourcesContext.languages, packageType);
context->self->m_packages.push_back(std::move(package));
if(packageType == APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE_APPLICATION)
{
context->mainPackages++;
}
return true;
});
dom->ForEachElementIn(dom->GetDocument(), XmlQueryName::Bundle_Packages_Package, visitorPackages);
ThrowErrorIf(Error::XmlError, (context.packageNames.size() == 0), "No packages in AppxBundleManifest.xml");
ThrowErrorIf(Error::AppxManifestSemanticError, (context.mainPackages == 0), "Bundle contains only resource packages");
}
HRESULT STDMETHODCALLTYPE AppxBundleManifestObject::GetPackageId(IAppxManifestPackageId **packageId) noexcept try
{
ThrowErrorIf(Error::InvalidParameter, (packageId == nullptr || *packageId != nullptr), "bad pointer");
auto package = m_packageId;
*packageId = package.Detach();
return static_cast<HRESULT>(Error::OK);
} CATCH_RETURN();
HRESULT STDMETHODCALLTYPE AppxBundleManifestObject::GetPackageInfoItems(IAppxBundleManifestPackageInfoEnumerator **packageInfoItems) noexcept try
{
ThrowErrorIf(Error::InvalidParameter, (packageInfoItems == nullptr || *packageInfoItems != nullptr), "bad pointer.");
*packageInfoItems = ComPtr<IAppxBundleManifestPackageInfoEnumerator>::
Make<EnumeratorCom<IAppxBundleManifestPackageInfoEnumerator, IAppxBundleManifestPackageInfo>>(m_packages).Detach();
return static_cast<HRESULT>(Error::OK);
} CATCH_RETURN();
HRESULT STDMETHODCALLTYPE AppxBundleManifestObject::GetStream(IStream **manifestStream) noexcept try
{
ThrowErrorIf(Error::InvalidParameter, (manifestStream == nullptr || *manifestStream != nullptr), "bad pointer");
auto stream = GetStream();
LARGE_INTEGER li{0};
ThrowHrIfFailed(stream->Seek(li, StreamBase::Reference::START, nullptr));
*manifestStream = stream.Detach();
return static_cast<HRESULT>(Error::OK);
} CATCH_RETURN();
AppxBundleManifestPackageInfo::AppxBundleManifestPackageInfo(
IMsixFactory* factory,
const std::string& name,
const std::string& bundleName,
const std::string& version,
const std::uint64_t size,
const std::uint64_t offset,
const std::string& resourceId,
const std::string& architecture,
const std::string& publisher,
std::vector<Bcp47Tag>& languages,
APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE packageType):
m_factory(factory), m_fileName(name), m_size(size), m_offset(offset), m_languages(std::move(languages)), m_packageType(packageType)
{
std::regex e (".+\\.((appx)|(msix))");
ThrowErrorIf(Error::AppxManifestSemanticError, !std::regex_match(m_fileName, e), "Invalid FileName attribute in AppxBundleManifest.xml");
m_packageId = ComPtr<IAppxManifestPackageId>::Make<AppxManifestPackageId>(factory, bundleName, version, resourceId, architecture, publisher);
}
// IAppxBundleManifestPackageInfo
HRESULT STDMETHODCALLTYPE AppxBundleManifestPackageInfo::GetPackageType(APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE *packageType) noexcept try
{
ThrowErrorIf(Error::InvalidParameter, (packageType == nullptr), "bad pointer");
*packageType = m_packageType;
return static_cast<HRESULT>(Error::OK);
} CATCH_RETURN();
HRESULT STDMETHODCALLTYPE AppxBundleManifestPackageInfo::GetPackageId(IAppxManifestPackageId **packageId) noexcept try
{
ThrowErrorIf(Error::InvalidParameter, (packageId == nullptr || *packageId != nullptr), "bad pointer");
auto package = m_packageId;
*packageId = package.Detach();
return static_cast<HRESULT>(Error::OK);
} CATCH_RETURN();
HRESULT STDMETHODCALLTYPE AppxBundleManifestPackageInfo::GetFileName(LPWSTR *fileName) noexcept try
{
return m_factory->MarshalOutString(m_fileName, fileName);
} CATCH_RETURN();
HRESULT STDMETHODCALLTYPE AppxBundleManifestPackageInfo::GetOffset(UINT64 *offset) noexcept try
{
ThrowErrorIf(Error::InvalidParameter, (offset == nullptr), "bad pointer");
*offset = m_offset;
return static_cast<HRESULT>(Error::OK);
} CATCH_RETURN();
HRESULT STDMETHODCALLTYPE AppxBundleManifestPackageInfo::GetSize(UINT64 *size) noexcept try
{
ThrowErrorIf(Error::InvalidParameter, (size == nullptr), "bad pointer");
*size = m_size;
return static_cast<HRESULT>(Error::OK);
} CATCH_RETURN();
HRESULT STDMETHODCALLTYPE AppxBundleManifestPackageInfo::GetResources(IAppxManifestQualifiedResourcesEnumerator **resources) noexcept try
{
ThrowErrorIf(Error::InvalidParameter, (resources == nullptr || *resources != nullptr), "bad pointer.");
std::vector<ComPtr<IAppxManifestQualifiedResource>> languages;
for(auto& bcp47 : m_languages)
{
auto resource = ComPtr<IAppxManifestQualifiedResource>::Make<AppxBundleQualifiedResource>(m_factory, bcp47.GetFullTag());
languages.push_back(std::move(resource));
}
*resources = ComPtr<IAppxManifestQualifiedResourcesEnumerator>::
Make<EnumeratorCom<IAppxManifestQualifiedResourcesEnumerator, IAppxManifestQualifiedResource>>(languages).Detach();
return static_cast<HRESULT>(Error::OK);
} CATCH_RETURN();
}

Просмотреть файл

@ -84,21 +84,33 @@ namespace MSIX {
// IAppxBundleFactory
HRESULT STDMETHODCALLTYPE AppxFactory::CreateBundleWriter(IStream *outputStream, UINT64 bundleVersion, IAppxBundleWriter **bundleWriter) noexcept
{
return static_cast<HRESULT>(Error::NotImplemented);
#ifdef BUNDLE_SUPPORT
return static_cast<HRESULT>(Error::NotImplemented);
#else
return static_cast<HRESULT>(MSIX::Error::NotSupported);
#endif
}
HRESULT STDMETHODCALLTYPE AppxFactory::CreateBundleReader(IStream *inputStream, IAppxBundleReader **bundleReader) noexcept try
{
ComPtr<IAppxPackageReader> reader;
ThrowHrIfFailed(CreatePackageReader(inputStream, &reader));
auto result = reader.As<IAppxBundleReader>();
*bundleReader = result.Detach();
return static_cast<HRESULT>(Error::OK);
#ifdef BUNDLE_SUPPORT
ComPtr<IAppxPackageReader> reader;
ThrowHrIfFailed(CreatePackageReader(inputStream, &reader));
auto result = reader.As<IAppxBundleReader>();
*bundleReader = result.Detach();
return static_cast<HRESULT>(Error::OK);
#else
return static_cast<HRESULT>(MSIX::Error::NotSupported);
#endif
} CATCH_RETURN();
HRESULT STDMETHODCALLTYPE AppxFactory::CreateBundleManifestReader(IStream *inputStream, IAppxBundleManifestReader **manifestReader) noexcept
{
return static_cast<HRESULT>(Error::NotImplemented);
#ifdef BUNDLE_SUPPORT
return static_cast<HRESULT>(Error::NotImplemented);
#else
return static_cast<HRESULT>(MSIX::Error::NotSupported);
#endif
}
// IMsixFactory

Просмотреть файл

@ -376,120 +376,4 @@ namespace MSIX {
*documentElement = m_dom->GetDocument().As<IMsixElement>().Detach();
return static_cast<HRESULT>(Error::OK);
} CATCH_RETURN();
AppxBundleManifestObject::AppxBundleManifestObject(IMsixFactory* factory, const ComPtr<IStream>& stream) : m_factory(factory), m_stream(stream)
{
ComPtr<IXmlFactory> xmlFactory;
ThrowHrIfFailed(m_factory->QueryInterface(UuidOfImpl<IXmlFactory>::iid, reinterpret_cast<void**>(&xmlFactory)));
auto dom = xmlFactory->CreateDomFromStream(XmlContentType::AppxBundleManifestXml, stream);
XmlVisitor visitorIdentity(static_cast<void*>(this), [](void* s, const ComPtr<IXmlElement>& identityNode)->bool
{
AppxBundleManifestObject* self = reinterpret_cast<AppxBundleManifestObject*>(s);
ThrowErrorIf(Error::AppxManifestSemanticError, (nullptr != self->m_packageId.Get()), "There must be only one Identity element at most in AppxBundleManifest.xml");
const auto& name = identityNode->GetAttributeValue(XmlAttributeName::Name);
const auto& publisher = identityNode->GetAttributeValue(XmlAttributeName::Publisher);
const auto& version = identityNode->GetAttributeValue(XmlAttributeName::Version);
ThrowErrorIf(Error::AppxManifestSemanticError, (publisher.empty()), "Invalid Identity element");
// Bundles don't have a ResourceId attribute in their manifest, but is always ~ for the package identity.
self->m_packageId = ComPtr<IAppxManifestPackageId>::Make<AppxManifestPackageId>(self->m_factory, name, version, "~", "neutral", publisher);
return true;
});
dom->ForEachElementIn(dom->GetDocument(), XmlQueryName::Bundle_Identity, visitorIdentity);
struct _context
{
AppxBundleManifestObject* self;
IXmlDom* dom;
std::vector<std::string> packageNames;
size_t mainPackages;
};
_context context = { this, dom.Get(), {} , 0};
XmlVisitor visitorPackages(static_cast<void*>(&context), [](void* c, const ComPtr<IXmlElement>& packageNode)->bool
{
_context* context = reinterpret_cast<_context*>(c);
const auto& name = packageNode->GetAttributeValue(XmlAttributeName::Bundle_Package_FileName);
std::ostringstream builder;
builder << "Duplicate file: '" << name << "' specified in AppxBundleManifest.xml.";
ThrowErrorIf(Error::AppxManifestSemanticError,
std::find(std::begin(context->packageNames), std::end(context->packageNames), name) != context->packageNames.end(),
builder.str().c_str());
context->packageNames.push_back(name);
const auto& version = packageNode->GetAttributeValue(XmlAttributeName::Version);
const auto& resourceId = packageNode->GetAttributeValue(XmlAttributeName::ResourceId);
const auto& architecture = packageNode->GetAttributeValue(XmlAttributeName::Bundle_Package_Architecture);
const auto& type = packageNode->GetAttributeValue(XmlAttributeName::Bundle_Package_Type);
const auto size = GetNumber<std::uint64_t>(packageNode, XmlAttributeName::Size, 0);
const auto offset = GetNumber<std::uint64_t>(packageNode, XmlAttributeName::Bundle_Package_Offset, 0);
// Default value is resource
APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE packageType = (type.empty() || type == "resource") ?
APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE_RESOURCE : APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE_APPLICATION;
struct _resourcesContext
{
std::vector<Bcp47Tag> languages;
bool hasResources;
};
_resourcesContext resourcesContext = { {}, false};
XmlVisitor visitor(static_cast<void*>(&resourcesContext), [](void* c, const ComPtr<IXmlElement>& resourceNode)->bool
{
_resourcesContext* resourcesContext = reinterpret_cast<_resourcesContext*>(c);
const auto& language = resourceNode->GetAttributeValue(XmlAttributeName::Language);
if (!language.empty()) { resourcesContext->languages.push_back(Bcp47Tag(language)); }
resourcesContext->hasResources = true;
return true;
});
context->dom->ForEachElementIn(packageNode, XmlQueryName::Bundle_Packages_Package_Resources_Resource, visitor);
if ((packageType == APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE_RESOURCE) && resourcesContext.languages.empty() && resourcesContext.hasResources)
{ // For now, we only support languages resource packages
return true;
}
ComPtr<IAppxManifestPackageIdInternal> packageIdInternal = context->self->m_packageId.As<IAppxManifestPackageIdInternal>();
auto package = ComPtr<IAppxBundleManifestPackageInfo>::Make<AppxBundleManifestPackageInfo>(
context->self->m_factory, name, packageIdInternal->GetName(), version, size, offset, resourceId,
architecture, packageIdInternal->GetPublisher(), resourcesContext.languages, packageType);
context->self->m_packages.push_back(std::move(package));
if(packageType == APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE_APPLICATION)
{
context->mainPackages++;
}
return true;
});
dom->ForEachElementIn(dom->GetDocument(), XmlQueryName::Bundle_Packages_Package, visitorPackages);
ThrowErrorIf(Error::XmlError, (context.packageNames.size() == 0), "No packages in AppxBundleManifest.xml");
ThrowErrorIf(Error::AppxManifestSemanticError, (context.mainPackages == 0), "Bundle contains only resource packages");
}
HRESULT STDMETHODCALLTYPE AppxBundleManifestObject::GetPackageId(IAppxManifestPackageId **packageId) noexcept try
{
ThrowErrorIf(Error::InvalidParameter, (packageId == nullptr || *packageId != nullptr), "bad pointer");
auto package = m_packageId;
*packageId = package.Detach();
return static_cast<HRESULT>(Error::OK);
} CATCH_RETURN();
HRESULT STDMETHODCALLTYPE AppxBundleManifestObject::GetPackageInfoItems(IAppxBundleManifestPackageInfoEnumerator **packageInfoItems) noexcept try
{
ThrowErrorIf(Error::InvalidParameter, (packageInfoItems == nullptr || *packageInfoItems != nullptr), "bad pointer.");
*packageInfoItems = ComPtr<IAppxBundleManifestPackageInfoEnumerator>::
Make<EnumeratorCom<IAppxBundleManifestPackageInfoEnumerator, IAppxBundleManifestPackageInfo>>(m_packages).Detach();
return static_cast<HRESULT>(Error::OK);
} CATCH_RETURN();
HRESULT STDMETHODCALLTYPE AppxBundleManifestObject::GetStream(IStream **manifestStream) noexcept try
{
ThrowErrorIf(Error::InvalidParameter, (manifestStream == nullptr || *manifestStream != nullptr), "bad pointer");
auto stream = GetStream();
LARGE_INTEGER li{0};
ThrowHrIfFailed(stream->Seek(li, StreamBase::Reference::START, nullptr));
*manifestStream = stream.Detach();
return static_cast<HRESULT>(Error::OK);
} CATCH_RETURN();
}

Просмотреть файл

@ -172,72 +172,4 @@ namespace MSIX {
ThrowErrorIfNot(Error::Unexpected, SHA256::ComputeHash(buffer.data(), static_cast<uint32_t>(buffer.size()), hash), "Failed computing publisherId");
return Base32Encoding(hash);
}
AppxBundleManifestPackageInfo::AppxBundleManifestPackageInfo(
IMsixFactory* factory,
const std::string& name,
const std::string& bundleName,
const std::string& version,
const std::uint64_t size,
const std::uint64_t offset,
const std::string& resourceId,
const std::string& architecture,
const std::string& publisher,
std::vector<Bcp47Tag>& languages,
APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE packageType):
m_factory(factory), m_fileName(name), m_size(size), m_offset(offset), m_languages(std::move(languages)), m_packageType(packageType)
{
std::regex e (".+\\.((appx)|(msix))");
ThrowErrorIf(Error::AppxManifestSemanticError, !std::regex_match(m_fileName, e), "Invalid FileName attribute in AppxBundleManifest.xml");
m_packageId = ComPtr<IAppxManifestPackageId>::Make<AppxManifestPackageId>(factory, bundleName, version, resourceId, architecture, publisher);
}
// IAppxBundleManifestPackageInfo
HRESULT STDMETHODCALLTYPE AppxBundleManifestPackageInfo::GetPackageType(APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE *packageType) noexcept try
{
ThrowErrorIf(Error::InvalidParameter, (packageType == nullptr), "bad pointer");
*packageType = m_packageType;
return static_cast<HRESULT>(Error::OK);
} CATCH_RETURN();
HRESULT STDMETHODCALLTYPE AppxBundleManifestPackageInfo::GetPackageId(IAppxManifestPackageId **packageId) noexcept try
{
ThrowErrorIf(Error::InvalidParameter, (packageId == nullptr || *packageId != nullptr), "bad pointer");
auto package = m_packageId;
*packageId = package.Detach();
return static_cast<HRESULT>(Error::OK);
} CATCH_RETURN();
HRESULT STDMETHODCALLTYPE AppxBundleManifestPackageInfo::GetFileName(LPWSTR *fileName) noexcept try
{
return m_factory->MarshalOutString(m_fileName, fileName);
} CATCH_RETURN();
HRESULT STDMETHODCALLTYPE AppxBundleManifestPackageInfo::GetOffset(UINT64 *offset) noexcept try
{
ThrowErrorIf(Error::InvalidParameter, (offset == nullptr), "bad pointer");
*offset = m_offset;
return static_cast<HRESULT>(Error::OK);
} CATCH_RETURN();
HRESULT STDMETHODCALLTYPE AppxBundleManifestPackageInfo::GetSize(UINT64 *size) noexcept try
{
ThrowErrorIf(Error::InvalidParameter, (size == nullptr), "bad pointer");
*size = m_size;
return static_cast<HRESULT>(Error::OK);
} CATCH_RETURN();
HRESULT STDMETHODCALLTYPE AppxBundleManifestPackageInfo::GetResources(IAppxManifestQualifiedResourcesEnumerator **resources) noexcept try
{
ThrowErrorIf(Error::InvalidParameter, (resources == nullptr || *resources != nullptr), "bad pointer.");
std::vector<ComPtr<IAppxManifestQualifiedResource>> languages;
for(auto& bcp47 : m_languages)
{
auto resource = ComPtr<IAppxManifestQualifiedResource>::Make<AppxBundleQualifiedResource>(m_factory, bcp47.GetFullTag());
languages.push_back(std::move(resource));
}
*resources = ComPtr<IAppxManifestQualifiedResourcesEnumerator>::
Make<EnumeratorCom<IAppxManifestQualifiedResourcesEnumerator, IAppxManifestQualifiedResource>>(languages).Detach();
return static_cast<HRESULT>(Error::OK);
} CATCH_RETURN();
}

Просмотреть файл

@ -11,12 +11,16 @@
#include "UnicodeConversion.hpp"
#include "IXml.hpp"
#include "MSIXResource.hpp"
#include "Applicability.hpp"
#include "AppxManifestObject.hpp"
#include "Encoding.hpp"
#include "Enumerators.hpp"
#include "AppxFile.hpp"
#ifdef BUNDLE_SUPPORT
#include "Applicability.hpp"
#include "AppxBundleManifest.hpp"
#endif
#include <string>
#include <vector>
#include <map>
@ -95,11 +99,18 @@ namespace MSIX {
}
else
{
std::string pathInWindows(APPXBUNDLEMANIFEST_XML);
std::replace(pathInWindows.begin(), pathInWindows.end(), '/', '\\');
stream = m_appxBlockMap->GetValidationStream(pathInWindows, appxBundleManifestInContainer);
m_appxBundleManifest = ComPtr<IVerifierObject>::Make<AppxBundleManifestObject>(factory, stream);
m_isBundle = true;
#ifdef BUNDLE_SUPPORT
std::string pathInWindows(APPXBUNDLEMANIFEST_XML);
std::replace(pathInWindows.begin(), pathInWindows.end(), '/', '\\');
stream = m_appxBlockMap->GetValidationStream(pathInWindows, appxBundleManifestInContainer);
m_appxBundleManifest = ComPtr<IVerifierObject>::Make<AppxBundleManifestObject>(factory, stream);
m_isBundle = true;
#else
// It is valid for a user to create an IAppxPackageReader and then QI for IAppxBundleReader, but
// not when bundle support is off.
ThrowErrorAndLog(Error::NotSupported, "Bundle functionality not supported");
#endif
}
if ((m_validation & MSIX_VALIDATION_OPTION_SKIPSIGNATURE) == 0)
@ -193,6 +204,8 @@ namespace MSIX {
auto blockMapInternal = m_appxBlockMap.As<IAppxBlockMapInternal>();
auto blockMapFiles = blockMapInternal->GetFileNames();
#ifdef BUNDLE_SUPPORT
if(m_isBundle)
{
// There should only be one file in the blockmap for bundles. We validate that the block map contains
@ -305,6 +318,7 @@ namespace MSIX {
}
else
{
#endif // BUNDLE_SUPPORT
for (const auto& fileName : blockMapFiles)
{ auto footPrintFile = std::find(std::begin(footPrintFileNames), std::end(footPrintFileNames), fileName);
if (footPrintFile == std::end(footPrintFileNames))
@ -323,7 +337,9 @@ namespace MSIX {
// If the map is not empty, there's a file in the container that didn't go to the footprint or payload
// files. (eg. payload file missing in the AppxBlockMap.xml)
ThrowErrorIfNot(Error::BlockMapSemanticError, (filesToProcess.empty()), "Payload file not described in AppxBlockMap.xml");
#ifdef BUNDLE_SUPPORT
}
#endif
}
// Verify file in OPC and BlockMap
@ -405,6 +421,8 @@ namespace MSIX {
ThrowHrIfFailed(sourceFile->CopyTo(targetFile.Get(), bytesCount, nullptr, nullptr));
}
}
#ifdef BUNDLE_SUPPORT
if(m_isBundle)
{
for(const auto& appx : m_applicablePackages)
@ -413,6 +431,7 @@ namespace MSIX {
static_cast<MSIX_PACKUNPACK_OPTION>(options | MSIX_PACKUNPACK_OPTION_CREATEPACKAGESUBFOLDER), to.Get());
}
}
#endif
}
// IStorageObject
@ -531,58 +550,74 @@ namespace MSIX {
// IAppxBundleReader
HRESULT STDMETHODCALLTYPE AppxPackageObject::GetFootprintFile(APPX_BUNDLE_FOOTPRINT_FILE_TYPE fileType, IAppxFile **footprintFile) noexcept try
{
if (!m_isBundle) { return static_cast<HRESULT>(Error::NotImplemented); }
ThrowErrorIf(Error::InvalidParameter, (footprintFile == nullptr || *footprintFile != nullptr), "bad pointer");
ThrowErrorIf(Error::FileNotFound, (static_cast<size_t>(fileType) > bundleFootprintFiles.size()), "unknown footprint file type");
std::string footprint (bundleFootprintFiles[fileType]);
auto result = GetAppxFile(footprint);
ThrowErrorIfNot(Error::FileNotFound, result, "Requested footprint file not in bundle")
// Clients expect the stream's pointer to be at the start of the file!
ComPtr<IStream> stream;
ThrowHrIfFailed(result->GetStream(&stream));
ThrowHrIfFailed(stream->Seek({0}, StreamBase::Reference::START, nullptr));
*footprintFile = result.Detach();
return static_cast<HRESULT>(Error::OK);
#ifdef BUNDLE_SUPPORT
if (!m_isBundle) { return static_cast<HRESULT>(Error::NotImplemented); }
ThrowErrorIf(Error::InvalidParameter, (footprintFile == nullptr || *footprintFile != nullptr), "bad pointer");
ThrowErrorIf(Error::FileNotFound, (static_cast<size_t>(fileType) > bundleFootprintFiles.size()), "unknown footprint file type");
std::string footprint (bundleFootprintFiles[fileType]);
auto result = GetAppxFile(footprint);
ThrowErrorIfNot(Error::FileNotFound, result, "Requested footprint file not in bundle")
// Clients expect the stream's pointer to be at the start of the file!
ComPtr<IStream> stream;
ThrowHrIfFailed(result->GetStream(&stream));
ThrowHrIfFailed(stream->Seek({0}, StreamBase::Reference::START, nullptr));
*footprintFile = result.Detach();
return static_cast<HRESULT>(Error::OK);
#else
return static_cast<HRESULT>(MSIX::Error::NotSupported);
#endif
} CATCH_RETURN();
HRESULT STDMETHODCALLTYPE AppxPackageObject::GetPayloadPackages(IAppxFilesEnumerator **payloadPackages) noexcept try
{
if (!m_isBundle) { return static_cast<HRESULT>(Error::NotImplemented); }
ThrowErrorIf(Error::InvalidParameter,(payloadPackages == nullptr || *payloadPackages != nullptr), "bad pointer");
std::vector<ComPtr<IAppxFile>> packages;
for (const auto& fileName : GetFileNames(FileNameOptions::PayloadOnly))
{
auto package = GetAppxFile(fileName);
ComPtr<IStream> stream;
ThrowHrIfFailed(package->GetStream(&stream));
ThrowHrIfFailed(stream->Seek({0}, StreamBase::Reference::START, nullptr));
packages.push_back(std::move(package));
}
*payloadPackages = ComPtr<IAppxFilesEnumerator>::
Make<EnumeratorCom<IAppxFilesEnumerator, IAppxFile>>(packages).Detach();
return static_cast<HRESULT>(Error::OK);
#ifdef BUNDLE_SUPPORT
if (!m_isBundle) { return static_cast<HRESULT>(Error::NotImplemented); }
ThrowErrorIf(Error::InvalidParameter,(payloadPackages == nullptr || *payloadPackages != nullptr), "bad pointer");
std::vector<ComPtr<IAppxFile>> packages;
for (const auto& fileName : GetFileNames(FileNameOptions::PayloadOnly))
{
auto package = GetAppxFile(fileName);
ComPtr<IStream> stream;
ThrowHrIfFailed(package->GetStream(&stream));
ThrowHrIfFailed(stream->Seek({0}, StreamBase::Reference::START, nullptr));
packages.push_back(std::move(package));
}
*payloadPackages = ComPtr<IAppxFilesEnumerator>::
Make<EnumeratorCom<IAppxFilesEnumerator, IAppxFile>>(packages).Detach();
return static_cast<HRESULT>(Error::OK);
#else
return static_cast<HRESULT>(MSIX::Error::NotSupported);
#endif
} CATCH_RETURN();
HRESULT STDMETHODCALLTYPE AppxPackageObject::GetPayloadPackage(LPCWSTR fileName, IAppxFile **payloadPackage) noexcept try
{
if (!m_isBundle) { return static_cast<HRESULT>(Error::NotImplemented); }
ThrowErrorIf(Error::InvalidParameter, (fileName == nullptr || payloadPackage == nullptr || *payloadPackage != nullptr), "bad pointer");
std::string name = utf16_to_utf8(fileName);
auto result = GetAppxFile(name);
ThrowErrorIfNot(Error::FileNotFound, result, "Requested package not in bundle")
// Clients expect the stream's pointer to be at the start of the file!
ComPtr<IStream> stream;
ThrowHrIfFailed(result->GetStream(&stream));
ThrowHrIfFailed(stream->Seek({0}, StreamBase::Reference::START, nullptr));
*payloadPackage = result.Detach();
#ifdef BUNDLE_SUPPORT
if (!m_isBundle) { return static_cast<HRESULT>(Error::NotImplemented); }
ThrowErrorIf(Error::InvalidParameter, (fileName == nullptr || payloadPackage == nullptr || *payloadPackage != nullptr), "bad pointer");
std::string name = utf16_to_utf8(fileName);
auto result = GetAppxFile(name);
ThrowErrorIfNot(Error::FileNotFound, result, "Requested package not in bundle")
// Clients expect the stream's pointer to be at the start of the file!
ComPtr<IStream> stream;
ThrowHrIfFailed(result->GetStream(&stream));
ThrowHrIfFailed(stream->Seek({0}, StreamBase::Reference::START, nullptr));
*payloadPackage = result.Detach();
return static_cast<HRESULT>(Error::OK);
#else
return static_cast<HRESULT>(MSIX::Error::NotSupported);
#endif
} CATCH_RETURN();
HRESULT STDMETHODCALLTYPE AppxPackageObject::GetManifest(IAppxBundleManifestReader **manifestReader) noexcept
{
if (!m_isBundle) { return static_cast<HRESULT>(Error::NotImplemented); }
ThrowErrorIf(Error::InvalidParameter,(manifestReader == nullptr || *manifestReader != nullptr), "bad pointer");
*manifestReader = m_appxBundleManifest.As<IAppxBundleManifestReader>().Detach();
return static_cast<HRESULT>(Error::OK);
#ifdef BUNDLE_SUPPORT
if (!m_isBundle) { return static_cast<HRESULT>(Error::NotImplemented); }
ThrowErrorIf(Error::InvalidParameter,(manifestReader == nullptr || *manifestReader != nullptr), "bad pointer");
*manifestReader = m_appxBundleManifest.As<IAppxBundleManifestReader>().Detach();
return static_cast<HRESULT>(Error::OK);
#else
return static_cast<HRESULT>(MSIX::Error::NotSupported);
#endif
}
}

Просмотреть файл

@ -88,12 +88,16 @@ MIDL_DEFINE_GUID(IID, IID_IXmlElement, 0xac94449e,0x442d,0x4bed,0x8f,0
MIDL_DEFINE_GUID(IID, IID_IXmlDom, 0x0e7a446e,0xbaf7,0x44c1,0xb3,0x8a,0x21,0x6b,0xfa,0x18,0xa1,0xa8);
MIDL_DEFINE_GUID(IID, IID_IXmlFactory, 0xf82a60ec,0xfbfc,0x4cb9,0xbc,0x04,0x1a,0x0f,0xe2,0xb4,0xd5,0xbe);
MIDL_DEFINE_GUID(IID, IID_IAppxBlockMapInternal, 0x67fed21a,0x70ef,0x4175,0x8f,0x12,0x41,0x5b,0x21,0x3a,0xb6,0xd2);
MIDL_DEFINE_GUID(IID, IID_IBundleInfo, 0xff82ffcd,0x747a,0x4df9,0x88,0x79,0x85,0x3a,0xb9,0xdd,0x15,0xa1);
MIDL_DEFINE_GUID(IID, IID_IAppxManifestObject, 0xeff6d561,0xa236,0x4058,0x9f,0x1d,0x8f,0x93,0x63,0x3f,0xba,0x4b);
MIDL_DEFINE_GUID(IID, IID_IAppxManifestPackageIdInternal, 0x76b7d3e1,0x768a,0x45cb,0x96,0x26,0xba,0x64,0x52,0xbe,0xd2,0xde);
MIDL_DEFINE_GUID(IID, IID_IAppxBundleManifestPackageInfoInternal, 0x32e6fcf0,0x729b,0x401d,0x9d,0xbc,0xf9,0x27,0xb4,0x94,0xf9,0xaf);
MIDL_DEFINE_GUID(IID, IID_IStreamInternal, 0x44d2a7a8,0xa165,0x4a6e,0xa5,0x6f,0xc7,0xc2,0x4d,0xe7,0x50,0x5c);
// Internal bundle interfaces
#ifdef BUNDLE_SUPPORT
MIDL_DEFINE_GUID(IID, IID_IBundleInfo, 0xff82ffcd,0x747a,0x4df9,0x88,0x79,0x85,0x3a,0xb9,0xdd,0x15,0xa1);
MIDL_DEFINE_GUID(IID, IID_IAppxBundleManifestPackageInfoInternal, 0x32e6fcf0,0x729b,0x401d,0x9d,0xbc,0xf9,0x27,0xb4,0x94,0xf9,0xaf);
#endif
// internal XML PAL interfaces
#ifdef USING_XERCES
MIDL_DEFINE_GUID(IID, IID_IXercesElement, 0x07d6ee0e,0x2165,0x4b90,0x80,0x24,0xe1,0x76,0x29,0x1e,0x77,0xdd);

Просмотреть файл

@ -22,6 +22,12 @@ if(XML_PARSER MATCHES msxml6)
add_definitions(-DUSING_MSXML=1)
endif()
if(SKIP_BUNDLES)
message(STATUS "Bundle support disabled.")
else()
add_definitions(-DBUNDLE_SUPPORT=1)
endif()
if(WIN32)
set(DirectoryObject PAL/FileSystem/Win32/DirectoryObject.cpp)
set(SHA256 PAL/SHA256/Win32/SHA256.cpp)
@ -165,8 +171,21 @@ else()
set(CompressionObjectCpp PAL/DataCompression/Zlib/CompressionObject.cpp)
endif()
set(BundleHeaders)
set(BundleSources)
if(NOT SKIP_BUNDLES)
list(APPEND BundleHeaders
../inc/Applicability.hpp
../inc/AppxBundleManifest.hpp
)
list(APPEND BundleSources
AppxBundleManifest.cpp
ApplicabilityCommon.cpp
${Applicability}
)
endif()
set(LIB_PRIVATE_HEADERS
../inc/Applicability.hpp
../inc/AppxBlockMapObject.hpp
../inc/AppxFactory.hpp
../inc/AppxFile.hpp
@ -196,6 +215,7 @@ set(LIB_PRIVATE_HEADERS
../inc/IXml.hpp
../inc/ZipFileStream.hpp
../inc/ZipObject.hpp
${BundleHeaders}
)
set(LIB_SOURCES
@ -212,13 +232,12 @@ set(LIB_SOURCES
UnicodeConversion.cpp
msix.cpp
ZipObject.cpp
ApplicabilityCommon.cpp
${DirectoryObject}
${SHA256}
${Signature}
${XmlParser}
${Applicability}
${CompressionObjectCpp}
${BundleSources}
)
# Copy out public headers
@ -300,29 +319,31 @@ endif()
if(AOSP)
target_link_libraries(${PROJECT_NAME} PRIVATE -latomic)
find_package(Java REQUIRED)
if(NOT ANDROID_SDK)
if(NOT DEFINED ENV{ANDROID_HOME})
message(FATAL_ERROR "ANDROID_HOME enviroment variable not found.")
if(NOT SKIP_BUNDLES) # This will change when we have JNI functionality that is not bundle related.
find_package(Java REQUIRED)
if(NOT ANDROID_SDK)
if(NOT DEFINED ENV{ANDROID_HOME})
message(FATAL_ERROR "ANDROID_HOME enviroment variable not found.")
endif()
set(ANDROID_SDK $ENV{ANDROID_HOME})
endif()
set(ANDROID_SDK $ENV{ANDROID_HOME})
if(NOT ANDROID_SDK_VERSION)
SET(ANDROID_SDK_VERSION 24)
endif()
if(ANDROID_SDK_VERSION LESS 24)
message(FATAL_ERROR "MSIX minimum Android SDK is 24")
endif()
include(UseJava)
message(STATUS "Android SDK = ${ANDROID_SDK}")
add_jar(${PROJECT_NAME}-jni
SOURCES
PAL/java/com/microsoft/msix/JniHelper.java
INCLUDE_JARS
${ANDROID_SDK}/platforms/android-${ANDROID_SDK_VERSION}/android.jar
OUTPUT_DIR
${CMAKE_LIBRARY_OUTPUT_DIRECTORY}
)
endif()
if(NOT ANDROID_SDK_VERSION)
SET(ANDROID_SDK_VERSION 24)
endif()
if(ANDROID_SDK_VERSION LESS 24)
message(FATAL_ERROR "MSIX minimum Android SDK is 24")
endif()
include(UseJava)
message(STATUS "Android SDK = ${ANDROID_SDK}")
add_jar(${PROJECT_NAME}-jni
SOURCES
PAL/java/com/microsoft/msix/JniHelper.java
INCLUDE_JARS
${ANDROID_SDK}/platforms/android-${ANDROID_SDK_VERSION}/android.jar
OUTPUT_DIR
${CMAKE_LIBRARY_OUTPUT_DIRECTORY}
)
endif()
if((IOS) OR (MACOS))

Просмотреть файл

@ -101,6 +101,7 @@ MSIX_API HRESULT STDMETHODCALLTYPE UnpackBundle(
char* utf8SourcePackage,
char* utf8Destination) noexcept try
{
#ifdef BUNDLE_SUPPORT
ThrowErrorIfNot(MSIX::Error::InvalidParameter,
(utf8SourcePackage != nullptr && utf8Destination != nullptr),
"Invalid parameters"
@ -120,6 +121,9 @@ MSIX_API HRESULT STDMETHODCALLTYPE UnpackBundle(
auto to = MSIX::ComPtr<IStorageObject>::Make<MSIX::DirectoryObject>(utf8Destination);
reader.As<IPackage>()->Unpack(packUnpackOptions, to.Get());
return static_cast<HRESULT>(MSIX::Error::OK);
#else
return static_cast<HRESULT>(MSIX::Error::NotSupported);
#endif
} CATCH_RETURN();
MSIX_API HRESULT STDMETHODCALLTYPE UnpackBundleFromStream(
@ -129,6 +133,7 @@ MSIX_API HRESULT STDMETHODCALLTYPE UnpackBundleFromStream(
IStream* stream,
char* utf8Destination) noexcept try
{
#ifdef BUNDLE_SUPPORT
ThrowErrorIfNot(MSIX::Error::InvalidParameter,
(stream != nullptr && utf8Destination != nullptr),
"Invalid parameters"
@ -145,6 +150,9 @@ MSIX_API HRESULT STDMETHODCALLTYPE UnpackBundleFromStream(
auto to = MSIX::ComPtr<IStorageObject>::Make<MSIX::DirectoryObject>(utf8Destination);
reader.As<IPackage>()->Unpack(packUnpackOptions, to.Get());
return static_cast<HRESULT>(MSIX::Error::OK);
#else
return static_cast<HRESULT>(MSIX::Error::NotSupported);
#endif
} CATCH_RETURN();
MSIX_API HRESULT STDMETHODCALLTYPE GetLogTextUTF8(COTASKMEMALLOC* memalloc, char** logText) noexcept try
@ -210,8 +218,12 @@ MSIX_API HRESULT STDMETHODCALLTYPE CoCreateAppxBundleFactoryWithHeap(
MSIX_APPLICABILITY_OPTIONS applicabilityOptions,
IAppxBundleFactory** appxBundleFactory) noexcept try
{
#ifdef BUNDLE_SUPPORT
*appxBundleFactory = MSIX::ComPtr<IAppxBundleFactory>::Make<MSIX::AppxFactory>(validationOption, applicabilityOptions, memalloc, memfree).Detach();
return static_cast<HRESULT>(MSIX::Error::OK);
#else
return static_cast<HRESULT>(MSIX::Error::NotSupported);
#endif
} CATCH_RETURN();
// Call specific for Windows. Default to call CoTaskMemAlloc and CoTaskMemFree
@ -220,7 +232,7 @@ MSIX_API HRESULT STDMETHODCALLTYPE CoCreateAppxBundleFactory(
MSIX_APPLICABILITY_OPTIONS applicabilityOptions,
IAppxBundleFactory** appxBundleFactory) noexcept
{
#ifdef WIN32
#if defined(WIN32) && defined(BUNDLE_SUPPORT)
return CoCreateAppxBundleFactoryWithHeap(CoTaskMemAlloc, CoTaskMemFree, validationOption, applicabilityOptions, appxBundleFactory);
#else
return static_cast<HRESULT>(MSIX::Error::NotSupported);