Merged PR 2461986: Add interface for applicability override
Added interface to override language applicability in bundle reader. Added sample to illustrate usage. Related work items: #19015501
This commit is contained in:
Родитель
35e69e4ec5
Коммит
49e5f4c1c9
|
@ -6,7 +6,9 @@ cmake_minimum_required(VERSION 3.8.0 FATAL_ERROR)
|
|||
add_subdirectory(ExtractContentsSample)
|
||||
add_subdirectory(BundleSample)
|
||||
add_subdirectory(OverrideStreamSample)
|
||||
add_subdirectory(OverrideLanguageSample)
|
||||
|
||||
add_dependencies(ExtractContentsSample msix)
|
||||
add_dependencies(BundleSample msix)
|
||||
add_dependencies(OverrideStreamSample msix)
|
||||
add_dependencies(OverrideLanguageSample msix)
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
# Copyright (C) 2017 Microsoft. All rights reserved.
|
||||
# See LICENSE file in the project root for full license information.
|
||||
|
||||
cmake_minimum_required(VERSION 3.8.0 FATAL_ERROR)
|
||||
project (OverrideLanguageSample)
|
||||
|
||||
# Define two variables in order not to repeat ourselves.
|
||||
set(BINARY_NAME OverrideLanguageSample)
|
||||
|
||||
if(WIN32)
|
||||
set(DESCRIPTION "OverrideLanguageSample manifest")
|
||||
configure_file(${CMAKE_PROJECT_ROOT}/manifest.cmakein ${CMAKE_CURRENT_BINARY_DIR}/${BINARY_NAME}.exe.manifest CRLF)
|
||||
set(MANIFEST ${CMAKE_CURRENT_BINARY_DIR}/${BINARY_NAME}.exe.manifest)
|
||||
endif()
|
||||
|
||||
add_executable(${BINARY_NAME}
|
||||
OverrideLanguageSample.cpp
|
||||
${MANIFEST}
|
||||
)
|
||||
|
||||
target_include_directories(${BINARY_NAME} PRIVATE ${CMAKE_BINARY_DIR}/src/msix)
|
||||
|
||||
add_dependencies(${BINARY_NAME} msix)
|
||||
if (LINUX OR AOSP)
|
||||
target_link_libraries(${BINARY_NAME} PRIVATE -latomic)
|
||||
endif()
|
||||
target_link_libraries(${BINARY_NAME} PRIVATE msix)
|
|
@ -0,0 +1,329 @@
|
|||
//
|
||||
// Copyright (C) 2017 Microsoft. All rights reserved.
|
||||
// See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
#include "AppxPackaging.hpp"
|
||||
#include "MSIXWindows.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <atomic>
|
||||
|
||||
#define RETURN_IF_FAILED(a) \
|
||||
{ HRESULT __hr = a; \
|
||||
if (FAILED(__hr)) \
|
||||
{ return __hr; } \
|
||||
}
|
||||
|
||||
// Stripped down ComPtr provided for those platforms that do not already have a ComPtr class.
|
||||
template <class T>
|
||||
class ComPtr
|
||||
{
|
||||
public:
|
||||
// default ctor
|
||||
ComPtr() = default;
|
||||
ComPtr(T* ptr) : m_ptr(ptr) { InternalAddRef(); }
|
||||
|
||||
// For use instead of ComPtr<T> t(new Foo(...)); given that the class has an Initialize function
|
||||
template<class U, class... Args>
|
||||
static HRESULT MakeAndInitialize(T** result, Args&&... args)
|
||||
{
|
||||
ComPtr<U> inner(new U());
|
||||
RETURN_IF_FAILED(inner->Initialize(std::forward<Args>(args)...));
|
||||
RETURN_IF_FAILED(inner->QueryInterface(UuidOfImpl<T>::iid, reinterpret_cast<void**>(result)));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// For use instead of ComPtr<T> t(new Foo(...));
|
||||
template<class U, class... Args>
|
||||
static ComPtr<T> Make(Args&&... args)
|
||||
{
|
||||
ComPtr<T> result;
|
||||
result.m_ptr = new U(std::forward<Args>(args)...);
|
||||
return result;
|
||||
}
|
||||
|
||||
~ComPtr() { InternalRelease(); }
|
||||
inline T* operator->() const { return m_ptr; }
|
||||
inline T* Get() const { return m_ptr; }
|
||||
|
||||
inline T** operator&()
|
||||
{
|
||||
InternalRelease();
|
||||
return &m_ptr;
|
||||
}
|
||||
|
||||
T* Detach()
|
||||
{
|
||||
T* temp = m_ptr;
|
||||
m_ptr = nullptr;
|
||||
return temp;
|
||||
}
|
||||
|
||||
protected:
|
||||
T* m_ptr = nullptr;
|
||||
|
||||
inline void InternalAddRef() { if (m_ptr) { m_ptr->AddRef(); } }
|
||||
inline void InternalRelease()
|
||||
{
|
||||
T* temp = m_ptr;
|
||||
if (temp)
|
||||
{
|
||||
m_ptr = nullptr;
|
||||
temp->Release();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Or you can use what-ever allocator/deallocator is best for your platform...
|
||||
LPVOID STDMETHODCALLTYPE MyAllocate(SIZE_T cb) { return std::malloc(cb); }
|
||||
void STDMETHODCALLTYPE MyFree(LPVOID pv) { std::free(pv); }
|
||||
|
||||
// Helper class to free string buffers obtained from the packaging APIs.
|
||||
template<typename T>
|
||||
class Text
|
||||
{
|
||||
public:
|
||||
T** operator&() { return &content; }
|
||||
~Text() { Cleanup(); }
|
||||
T* Get() { return content; }
|
||||
|
||||
T* content = nullptr;
|
||||
protected:
|
||||
void Cleanup() { if (content) { MyFree(content); content = nullptr; } }
|
||||
};
|
||||
|
||||
int Help()
|
||||
{
|
||||
std::cout << std::endl;
|
||||
std::cout << "Usage:" << std::endl;
|
||||
std::cout << "------" << std::endl;
|
||||
std::cout << "\t" << "OverrideLanguageSample <bundle> <languages ...>" << std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << "Description:" << std::endl;
|
||||
std::cout << "------------" << std::endl;
|
||||
std::cout << "\tSample to show the usage of IMsixFactoryOverrides for MSIX_FACTORY_EXTENSION_APPLICABILITY_LANGUAGES " << std::endl;
|
||||
std::cout << "\tusing language BCP47 tags from the command line." << std::endl;
|
||||
std::cout << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
class OverrideLanguages final : public IMsixApplicabilityLanguagesEnumerator
|
||||
{
|
||||
public:
|
||||
OverrideLanguages(char** languages, int numLanguages) : m_languages(languages), m_numLanguages(numLanguages) {}
|
||||
|
||||
// IUnknown
|
||||
virtual ULONG STDMETHODCALLTYPE AddRef() override
|
||||
{
|
||||
return ++m_ref;
|
||||
}
|
||||
|
||||
virtual ULONG STDMETHODCALLTYPE Release() override
|
||||
{
|
||||
if (--m_ref == 0)
|
||||
{
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
return m_ref;
|
||||
}
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) noexcept override
|
||||
{
|
||||
if (ppvObject == nullptr || *ppvObject != nullptr)
|
||||
{
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
*ppvObject = nullptr;
|
||||
if (riid == UuidOfImpl<IUnknown>::iid)
|
||||
{
|
||||
*ppvObject = static_cast<void*>(reinterpret_cast<IUnknown*>(this));
|
||||
AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
if (riid == UuidOfImpl<IMsixApplicabilityLanguagesEnumerator>::iid)
|
||||
{
|
||||
*ppvObject = static_cast<void*>(reinterpret_cast<IMsixApplicabilityLanguagesEnumerator*>(this));
|
||||
AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
// IMsixApplicabilityLanguagesEnumerator
|
||||
virtual HRESULT STDMETHODCALLTYPE GetCurrent(LPCSTR *bcp47Language) noexcept override
|
||||
{
|
||||
if (m_currentIndex < m_numLanguages)
|
||||
{
|
||||
*bcp47Language = m_languages[m_currentIndex];
|
||||
return S_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return E_BOUNDS;
|
||||
}
|
||||
}
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE GetHasCurrent(BOOL *hasCurrent) noexcept override
|
||||
{
|
||||
*hasCurrent = (m_currentIndex < m_numLanguages);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE MoveNext(BOOL *hasNext) noexcept override
|
||||
{
|
||||
if (m_currentIndex < m_numLanguages)
|
||||
{
|
||||
m_currentIndex++;
|
||||
*hasNext = (m_currentIndex < m_numLanguages);
|
||||
return S_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return E_BOUNDS;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
std::atomic<std::uint32_t> m_ref;
|
||||
char** m_languages = nullptr;
|
||||
int m_numLanguages = 0;
|
||||
int m_currentIndex = 0;
|
||||
};
|
||||
|
||||
HRESULT ShowInformationOfPackage(IAppxFile* packageFile)
|
||||
{
|
||||
Text<WCHAR> packageName;
|
||||
RETURN_IF_FAILED(packageFile->GetName(&packageName));
|
||||
std::wcout << L"\tName: " << packageName.Get() << std::endl;
|
||||
|
||||
ComPtr<IAppxFactory> factory;
|
||||
RETURN_IF_FAILED(CoCreateAppxFactoryWithHeap(
|
||||
MyAllocate,
|
||||
MyFree,
|
||||
MSIX_VALIDATION_OPTION::MSIX_VALIDATION_OPTION_SKIPSIGNATURE,
|
||||
&factory));
|
||||
|
||||
// Get stream of the package and package reader
|
||||
ComPtr<IStream> packageStream;
|
||||
RETURN_IF_FAILED(packageFile->GetStream(&packageStream));
|
||||
ComPtr<IAppxPackageReader> packageReader;
|
||||
RETURN_IF_FAILED(factory->CreatePackageReader(packageStream.Get(), &packageReader));
|
||||
|
||||
// Get information about the package from the manifest
|
||||
ComPtr<IAppxManifestReader> manifest;
|
||||
RETURN_IF_FAILED(packageReader->GetManifest(&manifest));
|
||||
ComPtr<IAppxManifestPackageId> bundlePackageId;
|
||||
RETURN_IF_FAILED(manifest->GetPackageId(&bundlePackageId));
|
||||
|
||||
// Get full name of the bundle
|
||||
Text<WCHAR> fullName;
|
||||
RETURN_IF_FAILED(bundlePackageId->GetPackageFullName(&fullName));
|
||||
std::wcout << L"\tFull Name: " << fullName.Get() << std::endl;
|
||||
|
||||
// Show what are the resources of the package.
|
||||
ComPtr<IAppxManifestResourcesEnumerator> resourcesEnum;
|
||||
RETURN_IF_FAILED(manifest->GetResources(&resourcesEnum));
|
||||
BOOL hasCurrent = FALSE;
|
||||
RETURN_IF_FAILED(resourcesEnum->GetHasCurrent(&hasCurrent));
|
||||
while (hasCurrent)
|
||||
{
|
||||
Text<WCHAR> resource;
|
||||
RETURN_IF_FAILED(resourcesEnum->GetCurrent(&resource));
|
||||
std::wcout << L"\tResource: " << resource.Get() << std::endl;
|
||||
RETURN_IF_FAILED(resourcesEnum->MoveNext(&hasCurrent));
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ShowInformationOfBundle(char* bundleName, char** languages, int numLanguages)
|
||||
{
|
||||
std::cout << "File: " << bundleName << std::endl;
|
||||
|
||||
// Initialize the factory with full validation and applicability options.
|
||||
ComPtr<IAppxBundleFactory> bundleFactory;
|
||||
RETURN_IF_FAILED(CoCreateAppxBundleFactoryWithHeap(
|
||||
MyAllocate,
|
||||
MyFree,
|
||||
MSIX_VALIDATION_OPTION::MSIX_VALIDATION_OPTION_SKIPSIGNATURE,
|
||||
MSIX_APPLICABILITY_OPTIONS::MSIX_APPLICABILITY_OPTION_FULL,
|
||||
&bundleFactory));
|
||||
|
||||
// Create our object that implements IMsixApplicabilityLanguagesEnumerator
|
||||
auto overrideLanguages = ComPtr<IMsixApplicabilityLanguagesEnumerator>::Make<OverrideLanguages>(languages, numLanguages);
|
||||
|
||||
// Get the IMsixFactoryOverrides and set the override.
|
||||
// Do this before using the factory to create the bundle reader.
|
||||
ComPtr<IMsixFactoryOverrides> factoryOverrides;
|
||||
RETURN_IF_FAILED(bundleFactory->QueryInterface(UuidOfImpl<IMsixFactoryOverrides>::iid, reinterpret_cast<void**>(&factoryOverrides)));
|
||||
RETURN_IF_FAILED(factoryOverrides->SpecifyExtension(MSIX_FACTORY_EXTENSION_APPLICABILITY_LANGUAGES, overrideLanguages.Get()));
|
||||
|
||||
// Create stream on the file provided.
|
||||
ComPtr<IStream> inputStream;
|
||||
RETURN_IF_FAILED(CreateStreamOnFile(const_cast<char*>(bundleName), true, &inputStream));
|
||||
|
||||
// Now get the bundle reader
|
||||
ComPtr<IAppxBundleReader> bundleReader;
|
||||
RETURN_IF_FAILED(bundleFactory->CreateBundleReader(inputStream.Get(), &bundleReader));
|
||||
|
||||
// Get basic information about this bundle from the bundle manifest
|
||||
ComPtr<IAppxBundleManifestReader> manifestReader;
|
||||
RETURN_IF_FAILED(bundleReader->GetManifest(&manifestReader));
|
||||
ComPtr<IAppxManifestPackageId> bundlePackageId;
|
||||
RETURN_IF_FAILED(manifestReader->GetPackageId(&bundlePackageId));
|
||||
|
||||
// Get full name of the bundle
|
||||
Text<WCHAR> fullName;
|
||||
RETURN_IF_FAILED(bundlePackageId->GetPackageFullName(&fullName));
|
||||
std::wcout << L"Full Name: " << fullName.Get() << std::endl;
|
||||
|
||||
// A bundle with the MSIX_FACTORY_EXTENSION_APPLICABILITY_LANGUAGES override
|
||||
// will only show the packages that are applicable to the list of languages
|
||||
// specified. Get the applicable packages by calling GetPayloadPackages.
|
||||
ComPtr<IAppxFilesEnumerator> applicablePackages;
|
||||
RETURN_IF_FAILED(bundleReader->GetPayloadPackages(&applicablePackages));
|
||||
|
||||
BOOL hasCurrent = FALSE;
|
||||
RETURN_IF_FAILED(applicablePackages->GetHasCurrent(&hasCurrent));
|
||||
std::wcout << L"Applicable Packages: " << std::endl;
|
||||
while (hasCurrent)
|
||||
{
|
||||
ComPtr<IAppxFile> applicablePackage;
|
||||
RETURN_IF_FAILED(applicablePackages->GetCurrent(&applicablePackage));
|
||||
RETURN_IF_FAILED(ShowInformationOfPackage(applicablePackage.Get()));
|
||||
std::wcout << std::endl;
|
||||
RETURN_IF_FAILED(applicablePackages->MoveNext(&hasCurrent));
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
if (argc < 3)
|
||||
{
|
||||
return Help();
|
||||
}
|
||||
|
||||
HRESULT hr = ShowInformationOfBundle(argv[1], argv + 2, argc - 2);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
std::cout << "Error: " << std::hex << hr << " while reading the bundle" << std::endl;
|
||||
Text<char> text;
|
||||
auto logResult = GetLogTextUTF8(MyAllocate, &text);
|
||||
if (0 == logResult)
|
||||
{
|
||||
std::cout << "LOG:" << std::endl << text.content << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "UNABLE TO GET LOG WITH HR=" << std::hex << logResult << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -50,6 +50,9 @@ namespace MSIX {
|
|||
Applicability(MSIX_APPLICABILITY_OPTIONS applicabilityFlags) : m_applicabilityFlags(applicabilityFlags)
|
||||
{}
|
||||
|
||||
void InitializeLanguages();
|
||||
void InitializeLanguages(IMsixApplicabilityLanguagesEnumerator* languagesEnumerator);
|
||||
|
||||
void AddPackageIfApplicable(ComPtr<IAppxPackageReader>& reader, std::string& packageName,
|
||||
const std::vector<Bcp47Tag>& packageLanguages, APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE packageType, bool hasQualifiedResources);
|
||||
|
||||
|
@ -65,5 +68,6 @@ namespace MSIX {
|
|||
std::vector<std::pair<std::string, ComPtr<IAppxPackageReader>>> m_variantFormPackages;
|
||||
std::vector<std::pair<std::string, ComPtr<IAppxPackageReader>>> m_extraApplicationPackages;
|
||||
MSIX_APPLICABILITY_OPTIONS m_applicabilityFlags = MSIX_APPLICABILITY_OPTIONS::MSIX_APPLICABILITY_OPTION_FULL;
|
||||
std::vector<Bcp47Tag> m_languages;
|
||||
};
|
||||
}
|
|
@ -71,5 +71,6 @@ namespace MSIX {
|
|||
std::vector<std::uint8_t> m_resourcesVector;
|
||||
MSIX_APPLICABILITY_OPTIONS m_applicabilityFlags;
|
||||
ComPtr<IMsixStreamFactory> m_streamFactory;
|
||||
ComPtr<IMsixApplicabilityLanguagesEnumerator> m_applicabilityLanguagesEnumerator;
|
||||
};
|
||||
}
|
|
@ -1121,6 +1121,7 @@ interface IMsixElement;
|
|||
interface IMsixElementEnumerator;
|
||||
interface IMsixFactoryOverrides;
|
||||
interface IMsixStreamFactory;
|
||||
interface IMsixApplicabilityLanguagesEnumerator;
|
||||
|
||||
#ifndef __IMsixDocumentElement_INTERFACE_DEFINED__
|
||||
#define __IMsixDocumentElement_INTERFACE_DEFINED__
|
||||
|
@ -1177,6 +1178,7 @@ EXTERN_C DECLSPEC_SELECTANY const IID IID_IMsixFactoryOverrides;
|
|||
enum MSIX_FACTORY_EXTENSION
|
||||
{
|
||||
MSIX_FACTORY_EXTENSION_STREAM_FACTORY = 0x1,
|
||||
MSIX_FACTORY_EXTENSION_APPLICABILITY_LANGUAGES = 0x2,
|
||||
} MSIX_FACTORY_EXTENSION;
|
||||
|
||||
// {0acedbdb-57cd-4aca-8cee-33fa52394316}
|
||||
|
@ -1203,6 +1205,25 @@ EXTERN_C DECLSPEC_SELECTANY const IID IID_IMsixStreamFactory;
|
|||
|
||||
#endif /* __IMsixStreamFactory_INTERFACE_DEFINED__ */
|
||||
|
||||
#ifndef __IMsixApplicabilityLanguagesEnumerator_INTERFACE_DEFINED__
|
||||
#define __IMsixApplicabilityLanguagesEnumerator_INTERFACE_DEFINED__
|
||||
|
||||
EXTERN_C DECLSPEC_SELECTANY const IID IID_IMsixApplicabilityLanguagesEnumerator;
|
||||
|
||||
// {BFC4655A-BE7A-456A-BC4E-2AF9481E8432}
|
||||
interface IMsixApplicabilityLanguagesEnumerator : public IUnknown
|
||||
{
|
||||
virtual HRESULT STDMETHODCALLTYPE GetCurrent(
|
||||
/* [retval][string][out] */ LPCSTR *bcp47Language) = 0;
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE GetHasCurrent(
|
||||
/* [retval][out] */ BOOL *hasCurrent) = 0;
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE MoveNext(
|
||||
/* [retval][out] */ BOOL *hasNext) = 0;
|
||||
};
|
||||
|
||||
#endif /* __IMsixApplicabilityLanguagesEnumerator_INTERFACE_DEFINED__ */
|
||||
|
||||
extern "C++" {
|
||||
typedef /* [v1_enum] */
|
||||
|
@ -1386,5 +1407,6 @@ SpecializeUuidOfImpl(IMsixElement);
|
|||
SpecializeUuidOfImpl(IMsixElementEnumerator);
|
||||
SpecializeUuidOfImpl(IMsixFactoryOverrides);
|
||||
SpecializeUuidOfImpl(IMsixStreamFactory);
|
||||
SpecializeUuidOfImpl(IMsixApplicabilityLanguagesEnumerator);
|
||||
|
||||
#endif //__appxpackaging_hpp__
|
|
@ -112,6 +112,16 @@
|
|||
typedef const WCHAR* LPCWSTR;
|
||||
#endif
|
||||
|
||||
#ifndef _LPSTR_DEFINED
|
||||
#define _LPSTR_DEFINED
|
||||
typedef char* LPSTR;
|
||||
#endif
|
||||
|
||||
#ifndef _LPCSTR_DEFINED
|
||||
#define _LPCSTR_DEFINED
|
||||
typedef const char* LPCSTR;
|
||||
#endif
|
||||
|
||||
#ifndef _BYTE_DEFINED
|
||||
#define _BYTE_DEFINED
|
||||
typedef unsigned char BYTE;
|
||||
|
@ -254,6 +264,10 @@
|
|||
#define E_NOTIMPL 0x80004001
|
||||
#endif
|
||||
|
||||
#ifndef E_BOUNDS
|
||||
#define E_BOUNDS 0x8000000b
|
||||
#endif
|
||||
|
||||
#if !defined (_SYS_GUID_OPERATORS_)
|
||||
#define _SYS_GUID_OPERATORS_
|
||||
|
||||
|
|
|
@ -136,6 +136,25 @@ namespace MSIX {
|
|||
return result;
|
||||
}
|
||||
|
||||
void Applicability::InitializeLanguages()
|
||||
{
|
||||
m_languages = GetLanguages();
|
||||
}
|
||||
|
||||
void Applicability::InitializeLanguages(IMsixApplicabilityLanguagesEnumerator* languagesEnumerator)
|
||||
{
|
||||
BOOL hasNext = FALSE;
|
||||
ThrowHrIfFailed(languagesEnumerator->GetHasCurrent(&hasNext));
|
||||
while (hasNext)
|
||||
{
|
||||
LPCSTR language = nullptr;
|
||||
ThrowHrIfFailed(languagesEnumerator->GetCurrent(&language));
|
||||
m_languages.push_back(std::string(language));
|
||||
|
||||
ThrowHrIfFailed(languagesEnumerator->MoveNext(&hasNext));
|
||||
}
|
||||
}
|
||||
|
||||
void Applicability::AddPackageIfApplicable(ComPtr<IAppxPackageReader>& reader, std::string& packageName,
|
||||
const std::vector<Bcp47Tag>& packageLanguages, APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE packageType, bool hasQualifiedResources)
|
||||
{
|
||||
|
@ -158,7 +177,7 @@ namespace MSIX {
|
|||
|
||||
bool hasMatch = false;
|
||||
bool hasVariantMatch = false;
|
||||
for (auto& systemLanguage : GetLanguages())
|
||||
for (auto& systemLanguage : m_languages)
|
||||
{
|
||||
for (auto& packageLanguage : packageLanguages)
|
||||
{
|
||||
|
|
|
@ -186,6 +186,10 @@ namespace MSIX {
|
|||
{
|
||||
ThrowHrIfFailed(extension->QueryInterface(UuidOfImpl<IMsixStreamFactory>::iid, reinterpret_cast<void**>(&m_streamFactory)));
|
||||
}
|
||||
else if (name == MSIX_FACTORY_EXTENSION_APPLICABILITY_LANGUAGES)
|
||||
{
|
||||
ThrowHrIfFailed(extension->QueryInterface(UuidOfImpl<IMsixApplicabilityLanguagesEnumerator>::iid, reinterpret_cast<void**>(&m_applicabilityLanguagesEnumerator)));
|
||||
}
|
||||
else
|
||||
{
|
||||
return static_cast<HRESULT>(Error::InvalidParameter);
|
||||
|
@ -205,6 +209,13 @@ namespace MSIX {
|
|||
*extension = m_streamFactory.As<IUnknown>().Detach();
|
||||
}
|
||||
}
|
||||
else if (name == MSIX_FACTORY_EXTENSION_APPLICABILITY_LANGUAGES)
|
||||
{
|
||||
if (m_applicabilityLanguagesEnumerator.Get() != nullptr)
|
||||
{
|
||||
*extension = m_applicabilityLanguagesEnumerator.As<IUnknown>().Detach();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return static_cast<HRESULT>(Error::InvalidParameter);
|
||||
|
|
|
@ -216,6 +216,21 @@ namespace MSIX {
|
|||
auto appxFactory = m_factory.As<IAppxFactory>();
|
||||
|
||||
Applicability applicability(applicabilityFlags);
|
||||
|
||||
auto factoryOverrides = m_factory.As<IMsixFactoryOverrides>();
|
||||
ComPtr<IUnknown> applicabilityLanguagesUnk;
|
||||
ThrowHrIfFailed(factoryOverrides->GetCurrentSpecifiedExtension(MSIX_FACTORY_EXTENSION_APPLICABILITY_LANGUAGES, &applicabilityLanguagesUnk));
|
||||
|
||||
if (applicabilityLanguagesUnk.Get() != nullptr)
|
||||
{
|
||||
auto applicabilityLanguagesEnumerator = applicabilityLanguagesUnk.As<IMsixApplicabilityLanguagesEnumerator>();
|
||||
applicability.InitializeLanguages(applicabilityLanguagesEnumerator.Get());
|
||||
}
|
||||
else
|
||||
{
|
||||
applicability.InitializeLanguages();
|
||||
}
|
||||
|
||||
for (const auto& package : bundleInfo->GetPackages())
|
||||
{
|
||||
auto bundleInfoInternal = package.As<IAppxBundleManifestPackageInfoInternal>();
|
||||
|
@ -232,7 +247,6 @@ namespace MSIX {
|
|||
// We should only do this for flat bundles. If we do it for normal bundles and the user specify a
|
||||
// stream factory we will basically unpack any package the user wants with the same name as the package
|
||||
// we are looking, which sounds dangerous.
|
||||
auto factoryOverrides = m_factory.As<IMsixFactoryOverrides>();
|
||||
ComPtr<IUnknown> streamFactoryUnk;
|
||||
ThrowHrIfFailed(factoryOverrides->GetCurrentSpecifiedExtension(MSIX_FACTORY_EXTENSION_STREAM_FACTORY, &streamFactoryUnk));
|
||||
|
||||
|
|
|
@ -78,6 +78,7 @@ MIDL_PUBLIC_GUID(IID, IID_IMsixElement,0x5B6786FF,0x6145,0x4F0E,0xB8,0xC9,0x8E,0
|
|||
MIDL_PUBLIC_GUID(IID, IID_IMsixElementEnumerator,0x7E7EA105,0xA4F9,0x4C12,0x9E,0xFA,0x98,0xEF,0x18,0x95,0x41,0x8A);
|
||||
MIDL_PUBLIC_GUID(IID, IID_IMsixFactoryOverrides,0x0ACEDBDB,0x57CD,0x4ACA,0X8C,0XEE,0X33,0XFA,0X52,0X39,0X43,0X16);
|
||||
MIDL_PUBLIC_GUID(IID, IID_IMsixStreamFactory,0XC74F4821,0X3B82,0X4AD5,0X98,0XEA,0X3D,0X52,0X68,0X1A,0XFF,0X56);
|
||||
MIDL_PUBLIC_GUID(IID, IID_IMsixApplicabilityLanguagesEnumerator,0xbfc4655a,0xbe7a,0x456a,0xbc,0x4e,0x2a,0xf9,0x48,0x1e,0x84,0x32);
|
||||
|
||||
// internal interfaces.
|
||||
MIDL_DEFINE_GUID(IID, IID_IPackage, 0x51B2C456,0xAAA9,0x46D6,0x8E,0xC9,0x29,0x82,0x20,0x55,0x91,0x89);
|
||||
|
|
|
@ -98,6 +98,7 @@ else()
|
|||
"IID_IMsixElementEnumerator"
|
||||
"IID_IMsixFactoryOverrides"
|
||||
"IID_IMsixStreamFactory"
|
||||
"IID_IMsixApplicabilityLanguagesEnumerator"
|
||||
)
|
||||
if((IOS) OR (MACOS))
|
||||
# on Apple platforms you can explicitly define which symbols are exported
|
||||
|
|
Загрузка…
Ссылка в новой задаче