Merged PR 1424038: Rename CrossPlat files from appx to MSIX
This change contains the renaming from xPlatAppx to MSIX Packaging SDK Binaries - xPlatAppx.dll -> msix.dll - MakexPlatAppx.exe -> makemsix.exe Export rename - UnpackAppx ->UnpackPackage Related work items: #15704951
|
@ -6,7 +6,7 @@ cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR)
|
|||
SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
||||
|
||||
MESSAGE (STATUS "--------------------------------")
|
||||
MESSAGE (STATUS "xPlatAppx")
|
||||
MESSAGE (STATUS "MSIX Packaging SDK")
|
||||
MESSAGE (STATUS "--------------------------------")
|
||||
|
||||
# Set build options
|
||||
|
@ -67,12 +67,12 @@ ENDIF()
|
|||
|
||||
# Set the version number of your project here (format is MAJOR.MINOR.PATCHLEVEL - e.g. 1.0.0)
|
||||
SET(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH})
|
||||
MESSAGE (STATUS "xPlatAppx version ${VERSION}")
|
||||
MESSAGE (STATUS "xPlatAppx branch name ${GIT_BRANCH_NAME}")
|
||||
MESSAGE (STATUS "MSIX Packaging SDK version ${VERSION}")
|
||||
MESSAGE (STATUS "MSIX Packaging SDK branch name ${GIT_BRANCH_NAME}")
|
||||
|
||||
# Configure Package.nuspec
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Package.nuspec.cmakein ${CMAKE_CURRENT_BINARY_DIR}/Package.nuspec CRLF)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Microsoft.xPlat.AppxPackaging.targets ${CMAKE_BINARY_DIR}/build/native/Microsoft.xPlat.AppxPackaging.targets)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Microsoft.MSIX.Packaging.targets ${CMAKE_BINARY_DIR}/build/native/Microsoft.MSIX.Packaging.targets)
|
||||
MESSAGE (STATUS "Package.Nuspec created")
|
||||
MESSAGE (STATUS "--------------------------------")
|
||||
|
||||
|
@ -195,7 +195,7 @@ SET(CMAKE_MACOSX_RPATH ON)
|
|||
add_subdirectory(lib)
|
||||
MESSAGE (STATUS " ")
|
||||
MESSAGE (STATUS "--------------------------------")
|
||||
MESSAGE (STATUS "xPlatAppx")
|
||||
MESSAGE (STATUS "MSIX Packaging SDK")
|
||||
MESSAGE (STATUS "--------------------------------")
|
||||
MESSAGE (STATUS "libs processed")
|
||||
add_subdirectory(src)
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" >
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)..\..\build\native\WIN32\src\xPlatAppx;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>HAS_XPLATAPPX;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>$(MSBuildThisFileDirectory)..\..\build\native\WIN32\src\msix;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>HAS_MSIX;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
</Project>
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0"?>
|
||||
<package >
|
||||
<metadata>
|
||||
<id>Microsoft.xPlat.AppxPackaging</id>
|
||||
<id>Microsoft.MSIX.Packaging</id>
|
||||
<version>${VERSION}</version>
|
||||
<authors>psmith@microsoft.com</authors>
|
||||
<owners>Xplat-appX@service.microsoft.com</owners>
|
||||
|
@ -30,7 +30,7 @@
|
|||
* 15424167 - Enable iOS build
|
||||
</releaseNotes>
|
||||
<copyright>Copyright (C) 2017 Microsoft</copyright>
|
||||
<tags>xPlatAppx Appx AppxPackaging native</tags>
|
||||
<tags>MSIX Appx AppxPackaging native</tags>
|
||||
<dependencies />
|
||||
</metadata>
|
||||
</package>
|
34
README.md
|
@ -1,11 +1,11 @@
|
|||
xPlatAppx
|
||||
MSIX Packaging SDK
|
||||
---------
|
||||
Copyright (c) 2017 Microsoft Corp.
|
||||
All rights reserved.
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
The xPlatAppx project is an effort to enable developers on a variety of platforms to package and unpackage
|
||||
The MSIX Packaging SDK project is an effort to enable developers on a variety of platforms to package and unpackage
|
||||
application packages for the purposes of distribution from either the Microsoft Windows Apps Store, or
|
||||
2nd/3rd party stores. To that end, the file format of these packages need to be in a format that is easily
|
||||
digestible to through the Microsoft Windows Apps Store back-end ingestion processes; which means that the
|
||||
|
@ -14,15 +14,14 @@ DESCRIPTION
|
|||
|
||||
OVERVIEW
|
||||
--------
|
||||
The xPlatAppx project includes:
|
||||
1. Cross platform API support for unpacakge of .appx package
|
||||
2. Developer tooling to build .appx package on Windows, MacOS and Linux.
|
||||
The MSIX Packaging SDK project includes:
|
||||
1. Cross platform API support for unpacakge of .appx package
|
||||
|
||||
The scheduling of the highlevel work listed above will be determined with respect to the relative priorities.
|
||||
|
||||
The xPlatAppx project includes:
|
||||
The MSIX Packaging SDK project includes:
|
||||
|
||||
xPlatAppx - A shared library (DLL on Win32, dylib on MacOs, SO on Linux) that exports a subset
|
||||
msix - A shared library (DLL on Win32, dylib on MacOs, SO on Linux and Android) that exports a subset
|
||||
of the functionality contained within appxpackaging.dll on Windows. See:
|
||||
https://msdn.microsoft.com/en-us/library/windows/desktop/hh446766(v=vs.85).aspx
|
||||
for additional details.
|
||||
|
@ -31,12 +30,11 @@ The scheduling of the highlevel work listed above will be determined with respec
|
|||
CoCreating IAppxFactory, a c-style export: CoCreateAppxFactory is provided instead.
|
||||
See sample folder at root of package for cross platform consumption examples
|
||||
|
||||
Finally, there are two additional exports: 'Pack' and 'Unpack' that provide
|
||||
simplified package and unpackage implementations respectively.
|
||||
Finally, there is one exports 'Unpack' that provides an simplified unpackage implementations.
|
||||
|
||||
MakeXplatAppx - A command line wrapper over the Pack and Unpack implementations. This tool exists
|
||||
primarily as a means of validating the implementation of xPlatAppx internal routines
|
||||
and is compiled for Win32, MacOS, and Linux platforms.
|
||||
makemsix - A command line wrapper over the Unpack implementation. This tool exists
|
||||
primarily as a means of validating the implementation of the MSIX Packaging SDK internal
|
||||
routines and is compiled for Win32, MacOS, and Linux platforms.
|
||||
|
||||
SETUP INSTRUCTIONS
|
||||
------------------
|
||||
|
@ -92,9 +90,9 @@ PREREQUISITES
|
|||
cmake -DCMAKE_ANDROID_NDK=c:/android-ndk ^
|
||||
-DCMAKE_ANDROID_NDK_TOOLCHAIN_VERSION=clang ^
|
||||
-DCMAKE_SYSTEM_NAME=Android ^
|
||||
-DCMAKE_SYSTEM_VERSION=27 ^
|
||||
-DCMAKE_SYSTEM_VERSION=19 ^
|
||||
-DCMAKE_ANDROID_ARCH_ABI=x86 ^
|
||||
-DCMAKE_ANDROID_STL_TYPE=c++_static ^
|
||||
-DCMAKE_ANDROID_STL_TYPE=c++_shared ^
|
||||
-DCMAKE_BUILD_TYPE=Release ^
|
||||
-DAOSP=on ^
|
||||
-G"Ninja" ..
|
||||
|
@ -123,12 +121,18 @@ BUILD
|
|||
|
||||
On Mac using make:
|
||||
./makemac
|
||||
./makeios
|
||||
|
||||
On Linux using make:
|
||||
./makelinux
|
||||
./makeaosp
|
||||
|
||||
|
||||
|
||||
SUPPORT
|
||||
-------
|
||||
TODO: write stuffs here
|
||||
|
||||
HOW TO CONTRIBUTE TO xPlatAppx
|
||||
HOW TO CONTRIBUTE TO MSIX Packaging SDK
|
||||
------------------------------
|
||||
TODO: write stuffs here
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# xplat\lib
|
||||
# MSIX\lib
|
||||
# Copyright (C) 2017 Microsoft
|
||||
# Created by Phil Smith (psmith@microsoft.com) on 10/19/2017
|
||||
cmake_minimum_required(VERSION 3.4.0 FATAL_ERROR)
|
||||
|
|
|
@ -59,8 +59,8 @@ printsetup
|
|||
mkdir .vs
|
||||
cd .vs
|
||||
|
||||
# clean up any old builds of xPlatAppx modules
|
||||
find . -name *xPlatAppx* -d | xargs rm -r
|
||||
# clean up any old builds of msix modules
|
||||
find . -name *msix* -d | xargs rm -r
|
||||
|
||||
cmake -DCMAKE_SYSTEM_NAME=Android \
|
||||
-DCMAKE_ANDROID_NDK="$ndk" \
|
||||
|
|
|
@ -37,8 +37,8 @@ printsetup
|
|||
mkdir .vs
|
||||
cd .vs
|
||||
|
||||
# clean up any old builds of xPlatAppx modules
|
||||
find . -name *xPlatAppx* -d | xargs rm -r
|
||||
# clean up any old builds of msix modules
|
||||
find . -name *msix* -d | xargs rm -r
|
||||
|
||||
cmake -DCMAKE_BUILD_TYPE=$build -DIOS=on -DCMAKE_TOOLCHAIN_FILE=../cmake/ios.cmake -DCMAKE_OSX_ARCHITECTURES=$arch ..
|
||||
make
|
|
@ -31,8 +31,8 @@ printsetup
|
|||
mkdir .vs
|
||||
cd .vs
|
||||
|
||||
# clean up any old builds of xPlatAppx modules
|
||||
find . -name *xPlatAppx* -d | xargs rm -r
|
||||
# clean up any old builds of msix modules
|
||||
find . -name *msix* -d | xargs rm -r
|
||||
|
||||
cmake -DCMAKE_BUILD_TYPE=$build -DLINUX=on ..
|
||||
make
|
||||
|
|
|
@ -31,8 +31,8 @@ printsetup
|
|||
mkdir .vs
|
||||
cd .vs
|
||||
|
||||
# clean up any old builds of xPlatAppx modules
|
||||
find . -name *xPlatAppx* -d | xargs rm -r
|
||||
# clean up any old builds of msix modules
|
||||
find . -name *msix* -d | xargs rm -r
|
||||
|
||||
cmake -DCMAKE_BUILD_TYPE=$build -DMACOS=on ..
|
||||
make
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# xplat\src
|
||||
# MSIX\src
|
||||
# Copyright (C) 2017 Microsoft
|
||||
# Created by Phil Smith (psmith@microsoft.com) on 10/19/2017
|
||||
|
||||
|
@ -9,4 +9,4 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/inc)
|
|||
|
||||
add_subdirectory(ExtractContentsSample)
|
||||
|
||||
ADD_DEPENDENCIES(ExtractContentsSample xPlatAppx)
|
||||
ADD_DEPENDENCIES(ExtractContentsSample msix)
|
|
@ -1,9 +1,9 @@
|
|||
# xplat\src\MakeXplat
|
||||
# MSIX\src\makemsix
|
||||
# Copyright (C) 2017 Microsoft
|
||||
# Created by Phil Smith (psmith@microsoft.com) on 10/19/2017
|
||||
|
||||
cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR)
|
||||
project (MakeXplat)
|
||||
project (makemsix)
|
||||
|
||||
# Define two variables in order not to repeat ourselves.
|
||||
set(BINARY_NAME ExtractContentsSample)
|
||||
|
@ -20,5 +20,5 @@ add_executable(${BINARY_NAME}
|
|||
# specify that this binary is to be built with C++14
|
||||
set_property(TARGET ${BINARY_NAME} PROPERTY CXX_STANDARD 14)
|
||||
|
||||
ADD_DEPENDENCIES(${BINARY_NAME} xPlatAppx)
|
||||
target_link_libraries(${BINARY_NAME} xPlatAppx)
|
||||
ADD_DEPENDENCIES(${BINARY_NAME} msix)
|
||||
target_link_libraries(${BINARY_NAME} msix)
|
|
@ -20,7 +20,7 @@
|
|||
#endif
|
||||
|
||||
#include "AppxPackaging.hpp"
|
||||
#include "AppxWindows.hpp"
|
||||
#include "MSIXWindows.hpp"
|
||||
|
||||
// Stripped down ComPtr provided for those platforms that do not already have a ComPtr class.
|
||||
template <class T>
|
||||
|
@ -92,25 +92,25 @@ struct State
|
|||
{
|
||||
bool CreatePackageSubfolder()
|
||||
{
|
||||
unpackOptions = static_cast<APPX_PACKUNPACK_OPTION>(unpackOptions | APPX_PACKUNPACK_OPTION::APPX_PACKUNPACK_OPTION_CREATEPACKAGESUBFOLDER);
|
||||
unpackOptions = static_cast<MSIX_PACKUNPACK_OPTION>(unpackOptions | MSIX_PACKUNPACK_OPTION::MSIX_PACKUNPACK_OPTION_CREATEPACKAGESUBFOLDER);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SkipManifestValidation()
|
||||
{
|
||||
validationOptions = static_cast<APPX_VALIDATION_OPTION>(validationOptions | APPX_VALIDATION_OPTION::APPX_VALIDATION_OPTION_SKIPAPPXMANIFEST);
|
||||
validationOptions = static_cast<MSIX_VALIDATION_OPTION>(validationOptions | MSIX_VALIDATION_OPTION::MSIX_VALIDATION_OPTION_SKIPAPPXMANIFEST);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SkipSignature()
|
||||
{
|
||||
validationOptions = static_cast<APPX_VALIDATION_OPTION>(validationOptions | APPX_VALIDATION_OPTION::APPX_VALIDATION_OPTION_SKIPSIGNATURE);
|
||||
validationOptions = static_cast<MSIX_VALIDATION_OPTION>(validationOptions | MSIX_VALIDATION_OPTION::MSIX_VALIDATION_OPTION_SKIPSIGNATURE);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AllowSignatureOriginUnknown()
|
||||
{
|
||||
validationOptions = static_cast<APPX_VALIDATION_OPTION>(validationOptions | APPX_VALIDATION_OPTION::APPX_VALIDATION_OPTION_ALLOWSIGNATUREORIGINUNKNOWN);
|
||||
validationOptions = static_cast<MSIX_VALIDATION_OPTION>(validationOptions | MSIX_VALIDATION_OPTION::MSIX_VALIDATION_OPTION_ALLOWSIGNATUREORIGINUNKNOWN);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -130,8 +130,8 @@ struct State
|
|||
|
||||
std::wstring packageName;
|
||||
std::wstring directoryName;
|
||||
APPX_VALIDATION_OPTION validationOptions = APPX_VALIDATION_OPTION::APPX_VALIDATION_OPTION_FULL;
|
||||
APPX_PACKUNPACK_OPTION unpackOptions = APPX_PACKUNPACK_OPTION::APPX_PACKUNPACK_OPTION_NONE;
|
||||
MSIX_VALIDATION_OPTION validationOptions = MSIX_VALIDATION_OPTION::MSIX_VALIDATION_OPTION_FULL;
|
||||
MSIX_PACKUNPACK_OPTION unpackOptions = MSIX_PACKUNPACK_OPTION::MSIX_PACKUNPACK_OPTION_NONE;
|
||||
};
|
||||
|
||||
// Displays contextual formatted help to the user.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# xplat\src
|
||||
# MSIX\src
|
||||
# Copyright (C) 2017 Microsoft
|
||||
# Created by Phil Smith (psmith@microsoft.com) on 10/19/2017
|
||||
|
||||
|
@ -8,10 +8,10 @@ ADD_CUSTOM_TARGET(SRC)
|
|||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/../cmake) # main (top) cmake dir
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/inc)
|
||||
|
||||
add_subdirectory(xPlatAppx)
|
||||
add_subdirectory(MakeXplat)
|
||||
add_subdirectory(msix)
|
||||
add_subdirectory(makemsix)
|
||||
|
||||
ADD_DEPENDENCIES(MakeXplat xPlatAppx)
|
||||
ADD_DEPENDENCIES(makemsix msix)
|
||||
|
||||
# Create header for BlockMap schemas
|
||||
|
||||
|
@ -22,14 +22,11 @@ file(READ "${CMAKE_PROJECT_ROOT}/certs/base64_Windows_Production.cer" BASE64_WIN
|
|||
file(READ "${CMAKE_PROJECT_ROOT}/certs/base64_Windows_Production_PCA_2011.cer" BASE64_WINDOWS_PRODUCTION_PCA_2011)
|
||||
file(READ "${CMAKE_PROJECT_ROOT}/certs/Microsoft_MarketPlace_PCA_2011.cer" BASE64_MSFT_MARKETPLACE_CA_G_016)
|
||||
|
||||
# set(PEM_CERTS "${BASE64_MSFT_RCA_2010}${BASE64_MSFT_RCA_2011}${BASE64_WINDOWS_PRODUCTION}${BASE64_WINDOWS_PRODUCTION_PCA_2011}${BASE64_STORE_PCA_2011}")
|
||||
# file(WRITE "/Users/admin/Documents/foo.pem" "${PEM_CERTS}")
|
||||
|
||||
set(APPX_CERTS "// This file is generated by CMake and contains certs for parsing the AppxBlockMap.xml. Do not edit!!
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace xPlat {
|
||||
namespace MSIX {
|
||||
|
||||
// Do not alter the order of these certificates -- they are in chain order
|
||||
std::vector<std::string> appxCerts = {
|
||||
|
|
|
@ -16,12 +16,12 @@
|
|||
#include "BlockMapStream.hpp"
|
||||
#include "xercesc/util/XMLString.hpp"
|
||||
|
||||
namespace xPlat {
|
||||
namespace MSIX {
|
||||
|
||||
class AppxBlockMapBlock : public xPlat::ComClass<AppxBlockMapBlock, IAppxBlockMapBlock>
|
||||
class AppxBlockMapBlock : public MSIX::ComClass<AppxBlockMapBlock, IAppxBlockMapBlock>
|
||||
{
|
||||
public:
|
||||
AppxBlockMapBlock(IxPlatFactory* factory, Block* block) :
|
||||
AppxBlockMapBlock(IMSIXFactory* factory, Block* block) :
|
||||
m_factory(factory),
|
||||
m_block(block)
|
||||
{}
|
||||
|
@ -43,11 +43,11 @@ namespace xPlat {
|
|||
}
|
||||
|
||||
private:
|
||||
IxPlatFactory* m_factory;
|
||||
IMSIXFactory* m_factory;
|
||||
Block* m_block;
|
||||
};
|
||||
|
||||
class AppxBlockMapBlocksEnumerator : public xPlat::ComClass<AppxBlockMapBlocksEnumerator, IAppxBlockMapBlocksEnumerator>
|
||||
class AppxBlockMapBlocksEnumerator : public MSIX::ComClass<AppxBlockMapBlocksEnumerator, IAppxBlockMapBlocksEnumerator>
|
||||
{
|
||||
protected:
|
||||
std::vector<ComPtr<IAppxBlockMapBlock>>* m_blocks;
|
||||
|
@ -83,11 +83,11 @@ namespace xPlat {
|
|||
}
|
||||
};
|
||||
|
||||
class AppxBlockMapFile : public xPlat::ComClass<AppxBlockMapFile, IAppxBlockMapFile>
|
||||
class AppxBlockMapFile : public MSIX::ComClass<AppxBlockMapFile, IAppxBlockMapFile>
|
||||
{
|
||||
public:
|
||||
AppxBlockMapFile(
|
||||
IxPlatFactory* factory,
|
||||
IMSIXFactory* factory,
|
||||
std::vector<Block>* blocks,
|
||||
std::uint32_t localFileHeaderSize,
|
||||
const std::string& name,
|
||||
|
@ -156,13 +156,13 @@ namespace xPlat {
|
|||
|
||||
std::vector<ComPtr<IAppxBlockMapBlock>> m_blockMapBlocks;
|
||||
std::vector<Block>* m_blocks;
|
||||
IxPlatFactory* m_factory;
|
||||
IMSIXFactory* m_factory;
|
||||
std::uint32_t m_localFileHeaderSize;
|
||||
std::string m_name;
|
||||
std::uint64_t m_uncompressedSize;
|
||||
};
|
||||
|
||||
class AppxBlockMapFilesEnumerator : public xPlat::ComClass<AppxBlockMapFilesEnumerator, IAppxBlockMapFilesEnumerator>
|
||||
class AppxBlockMapFilesEnumerator : public MSIX::ComClass<AppxBlockMapFilesEnumerator, IAppxBlockMapFilesEnumerator>
|
||||
{
|
||||
protected:
|
||||
ComPtr<IAppxBlockMapReader> m_reader;
|
||||
|
@ -200,16 +200,16 @@ namespace xPlat {
|
|||
};
|
||||
|
||||
// Object backed by AppxBlockMap.xml
|
||||
class AppxBlockMapObject : public xPlat::ComClass<AppxBlockMapObject, IAppxBlockMapReader, IVerifierObject, IStorageObject>
|
||||
class AppxBlockMapObject : public MSIX::ComClass<AppxBlockMapObject, IAppxBlockMapReader, IVerifierObject, IStorageObject>
|
||||
{
|
||||
public:
|
||||
AppxBlockMapObject(IxPlatFactory* factory, ComPtr<IStream>& stream);
|
||||
AppxBlockMapObject(IMSIXFactory* factory, ComPtr<IStream>& stream);
|
||||
|
||||
// IVerifierObject
|
||||
const std::string& GetPublisher() override { throw Exception(Error::NotSupported); }
|
||||
bool HasStream() override { return m_stream.Get() != nullptr; }
|
||||
xPlat::ComPtr<IStream> GetStream() override { return m_stream; }
|
||||
xPlat::ComPtr<IStream> GetValidationStream(const std::string& part, IStream* stream) override;
|
||||
MSIX::ComPtr<IStream> GetStream() override { return m_stream; }
|
||||
MSIX::ComPtr<IStream> GetValidationStream(const std::string& part, IStream* stream) override;
|
||||
|
||||
// IAppxBlockMapReader
|
||||
HRESULT STDMETHODCALLTYPE GetFile(LPCWSTR filename, IAppxBlockMapFile **file) override;
|
||||
|
@ -222,13 +222,13 @@ namespace xPlat {
|
|||
std::vector<std::string> GetFileNames(FileNameOptions options) override;
|
||||
IStream* GetFile(const std::string& fileName) override;
|
||||
void RemoveFile(const std::string& fileName) override;
|
||||
IStream* OpenFile(const std::string& fileName, xPlat::FileStream::Mode mode) override;
|
||||
IStream* OpenFile(const std::string& fileName, MSIX::FileStream::Mode mode) override;
|
||||
void CommitChanges() override;
|
||||
|
||||
protected:
|
||||
std::map<std::string, std::vector<Block>> m_blockMap;
|
||||
std::map<std::string, ComPtr<IAppxBlockMapFile>> m_blockMapfiles;
|
||||
IxPlatFactory* m_factory;
|
||||
IMSIXFactory* m_factory;
|
||||
ComPtr<IStream> m_stream;
|
||||
};
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "AppxPackaging.hpp"
|
||||
#include "AppxWindows.hpp"
|
||||
#include "MSIXWindows.hpp"
|
||||
#include "ComHelper.hpp"
|
||||
#include "xercesc/util/PlatformUtils.hpp"
|
||||
|
||||
|
@ -9,29 +9,29 @@
|
|||
#include <vector>
|
||||
|
||||
// internal interface
|
||||
EXTERN_C const IID IID_IxPlatFactory;
|
||||
EXTERN_C const IID IID_IMSIXFactory;
|
||||
#ifndef WIN32
|
||||
// {1f850db4-32b8-4db6-8bf4-5a897eb611f1}
|
||||
interface IxPlatFactory : public IUnknown
|
||||
interface IMSIXFactory : public IUnknown
|
||||
#else
|
||||
#include "UnKnwn.h"
|
||||
#include "Objidl.h"
|
||||
class IxPlatFactory : public IUnknown
|
||||
class IMSIXFactory : public IUnknown
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
virtual HRESULT MarshalOutString(std::string& internal, LPWSTR *result) = 0;
|
||||
virtual HRESULT MarshalOutBytes(std::vector<std::uint8_t>& data, UINT32* size, BYTE** buffer) = 0;
|
||||
virtual APPX_VALIDATION_OPTION GetValidationOptions() = 0;
|
||||
virtual MSIX_VALIDATION_OPTION GetValidationOptions() = 0;
|
||||
};
|
||||
|
||||
SpecializeUuidOfImpl(IxPlatFactory);
|
||||
SpecializeUuidOfImpl(IMSIXFactory);
|
||||
|
||||
namespace xPlat {
|
||||
class AppxFactory : public ComClass<AppxFactory, IxPlatFactory, IAppxFactory>
|
||||
namespace MSIX {
|
||||
class AppxFactory : public ComClass<AppxFactory, IMSIXFactory, IAppxFactory>
|
||||
{
|
||||
public:
|
||||
AppxFactory(APPX_VALIDATION_OPTION validationOptions, COTASKMEMALLOC* memalloc, COTASKMEMFREE* memfree ) :
|
||||
AppxFactory(MSIX_VALIDATION_OPTION validationOptions, COTASKMEMALLOC* memalloc, COTASKMEMFREE* memfree ) :
|
||||
m_validationOptions(validationOptions), m_memalloc(memalloc), m_memfree(memfree)
|
||||
{
|
||||
ThrowErrorIf(Error::InvalidParameter, (m_memalloc == nullptr || m_memfree == nullptr), "allocator/deallocator pair not specified.")
|
||||
|
@ -58,13 +58,13 @@ namespace xPlat {
|
|||
LPCWSTR signatureFileName,
|
||||
IAppxBlockMapReader** blockMapReader) override;
|
||||
|
||||
// IxPlatFactory
|
||||
// IMSIXFactory
|
||||
HRESULT MarshalOutString(std::string& internal, LPWSTR *result) override;
|
||||
HRESULT MarshalOutBytes(std::vector<std::uint8_t>& data, UINT32* size, BYTE** buffer) override;
|
||||
APPX_VALIDATION_OPTION GetValidationOptions() override { return m_validationOptions; }
|
||||
MSIX_VALIDATION_OPTION GetValidationOptions() override { return m_validationOptions; }
|
||||
|
||||
COTASKMEMALLOC* m_memalloc;
|
||||
COTASKMEMFREE* m_memfree;
|
||||
APPX_VALIDATION_OPTION m_validationOptions;
|
||||
MSIX_VALIDATION_OPTION m_validationOptions;
|
||||
};
|
||||
}
|
|
@ -6,7 +6,7 @@
|
|||
#include <memory>
|
||||
|
||||
#include "AppxPackaging.hpp"
|
||||
#include "AppxWindows.hpp"
|
||||
#include "MSIXWindows.hpp"
|
||||
#include "Exceptions.hpp"
|
||||
#include "ComHelper.hpp"
|
||||
#include "StreamBase.hpp"
|
||||
|
@ -19,25 +19,24 @@
|
|||
#include "AppxFactory.hpp"
|
||||
|
||||
// internal interface
|
||||
EXTERN_C const IID IID_IAppxPackage;
|
||||
EXTERN_C const IID IID_IPackage;
|
||||
#ifndef WIN32
|
||||
// {51b2c456-aaa9-46d6-8ec9-298220559189}
|
||||
interface IAppxPackage : public IUnknown
|
||||
interface IPackage : public IUnknown
|
||||
#else
|
||||
#include "Unknwn.h"
|
||||
#include "Objidl.h"
|
||||
class IAppxPackage : public IUnknown
|
||||
class IPackage : public IUnknown
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
virtual void Pack(APPX_PACKUNPACK_OPTION options, const std::string& certFile, IStorageObject* from) = 0;
|
||||
virtual void Unpack(APPX_PACKUNPACK_OPTION options, IStorageObject* to) = 0;
|
||||
virtual void Unpack(MSIX_PACKUNPACK_OPTION options, IStorageObject* to) = 0;
|
||||
virtual std::vector<std::string>& GetFootprintFiles() = 0;
|
||||
};
|
||||
|
||||
SpecializeUuidOfImpl(IAppxPackage);
|
||||
SpecializeUuidOfImpl(IPackage);
|
||||
|
||||
namespace xPlat {
|
||||
namespace MSIX {
|
||||
// The 5-tuple that describes the identity of a package
|
||||
struct AppxPackageId
|
||||
{
|
||||
|
@ -75,8 +74,8 @@ namespace xPlat {
|
|||
// IVerifierObject
|
||||
const std::string& GetPublisher() override { return GetPackageId()->Publisher; }
|
||||
bool HasStream() override { return m_stream.Get() != nullptr; }
|
||||
xPlat::ComPtr<IStream> GetStream() override { return m_stream; }
|
||||
xPlat::ComPtr<IStream> GetValidationStream(const std::string& part, IStream* stream) override
|
||||
MSIX::ComPtr<IStream> GetStream() override { return m_stream; }
|
||||
MSIX::ComPtr<IStream> GetValidationStream(const std::string& part, IStream* stream) override
|
||||
{
|
||||
throw Exception(Error::NotSupported);
|
||||
}
|
||||
|
@ -90,15 +89,14 @@ namespace xPlat {
|
|||
};
|
||||
|
||||
// Storage object representing the entire AppxPackage
|
||||
class AppxPackageObject : public ComClass<AppxPackageObject, IAppxPackageReader, IAppxPackage, IStorageObject>
|
||||
class AppxPackageObject : public ComClass<AppxPackageObject, IAppxPackageReader, IPackage, IStorageObject>
|
||||
{
|
||||
public:
|
||||
AppxPackageObject(IxPlatFactory* factory, APPX_VALIDATION_OPTION validation, IStorageObject* container);
|
||||
AppxPackageObject(IMSIXFactory* factory, MSIX_VALIDATION_OPTION validation, IStorageObject* container);
|
||||
~AppxPackageObject() {}
|
||||
|
||||
// internal IxPlatAppxPackage methods
|
||||
void Pack(APPX_PACKUNPACK_OPTION options, const std::string& certFile, IStorageObject* from) override;
|
||||
void Unpack(APPX_PACKUNPACK_OPTION options, IStorageObject* to) override;
|
||||
// internal IPackage methods
|
||||
void Unpack(MSIX_PACKUNPACK_OPTION options, IStorageObject* to) override;
|
||||
|
||||
// IAppxPackageReader
|
||||
HRESULT STDMETHODCALLTYPE GetBlockMap(IAppxBlockMapReader** blockMapReader) override;
|
||||
|
@ -107,7 +105,7 @@ namespace xPlat {
|
|||
HRESULT STDMETHODCALLTYPE GetPayloadFiles(IAppxFilesEnumerator** filesEnumerator) override;
|
||||
HRESULT STDMETHODCALLTYPE GetManifest(IAppxManifestReader** manifestReader) override;
|
||||
|
||||
// returns a list of the footprint files found within this appx package.
|
||||
// returns a list of the footprint files found within this package.
|
||||
std::vector<std::string>& GetFootprintFiles() override { return m_footprintFiles; }
|
||||
|
||||
// IStorageObject methods
|
||||
|
@ -115,14 +113,14 @@ namespace xPlat {
|
|||
std::vector<std::string> GetFileNames(FileNameOptions options) override;
|
||||
IStream* GetFile(const std::string& fileName) override;
|
||||
void RemoveFile(const std::string& fileName) override;
|
||||
IStream* OpenFile(const std::string& fileName, xPlat::FileStream::Mode mode) override;
|
||||
IStream* OpenFile(const std::string& fileName, MSIX::FileStream::Mode mode) override;
|
||||
void CommitChanges() override;
|
||||
|
||||
protected:
|
||||
std::map<std::string, ComPtr<IStream>> m_streams;
|
||||
|
||||
APPX_VALIDATION_OPTION m_validation = APPX_VALIDATION_OPTION::APPX_VALIDATION_OPTION_FULL;
|
||||
ComPtr<IxPlatFactory> m_factory;
|
||||
MSIX_VALIDATION_OPTION m_validation = MSIX_VALIDATION_OPTION::MSIX_VALIDATION_OPTION_FULL;
|
||||
ComPtr<IMSIXFactory> m_factory;
|
||||
ComPtr<IVerifierObject> m_appxSignature;
|
||||
ComPtr<IVerifierObject> m_appxBlockMap;
|
||||
ComPtr<IVerifierObject> m_appxManifest;
|
||||
|
@ -133,7 +131,7 @@ namespace xPlat {
|
|||
std::vector<std::string> m_footprintFiles;
|
||||
};
|
||||
|
||||
class AppxFilesEnumerator : public xPlat::ComClass<AppxFilesEnumerator, IAppxFilesEnumerator>
|
||||
class AppxFilesEnumerator : public MSIX::ComClass<AppxFilesEnumerator, IAppxFilesEnumerator>
|
||||
{
|
||||
protected:
|
||||
ComPtr<IStorageObject> m_storage;
|
||||
|
|
|
@ -6,13 +6,13 @@
|
|||
// - Remove C style interfaces declaration
|
||||
// - Remove MIDL_INTERFACE MACRO
|
||||
// - Add IUnknown, ISequentialStream and IStream interfaces
|
||||
// - Add xPlatAppx specific funcions and helpers (See bottom of file)
|
||||
// - Add MSIX specific funcions and helpers (See bottom of file)
|
||||
// - See more changes in AppxPackaging_i.cpp
|
||||
|
||||
#ifndef __appxpackaging_hpp__
|
||||
#define __appxpackaging_hpp__
|
||||
|
||||
#include "AppxWindows.hpp"
|
||||
#include "MSIXWindows.hpp"
|
||||
|
||||
#ifdef WIN32
|
||||
#include <AppxPackaging.h>
|
||||
|
@ -1986,28 +1986,28 @@ EXTERN_C const IID IID_IAppxEncryptedBundleWriter2;
|
|||
} // extern "C"
|
||||
#endif // #ifdef WIN32
|
||||
|
||||
// MSIX specific
|
||||
|
||||
extern "C++" {
|
||||
typedef /* [v1_enum] */
|
||||
enum APPX_VALIDATION_OPTION
|
||||
enum MSIX_VALIDATION_OPTION
|
||||
{
|
||||
APPX_VALIDATION_OPTION_FULL = 0x0,
|
||||
APPX_VALIDATION_OPTION_SKIPSIGNATURE = 0x1,
|
||||
APPX_VALIDATION_OPTION_ALLOWSIGNATUREORIGINUNKNOWN = 0x2,
|
||||
APPX_VALIDATION_OPTION_SKIPAPPXMANIFEST = 0x4
|
||||
} APPX_VALIDATION_OPTION;
|
||||
MSIX_VALIDATION_OPTION_FULL = 0x0,
|
||||
MSIX_VALIDATION_OPTION_SKIPSIGNATURE = 0x1,
|
||||
MSIX_VALIDATION_OPTION_ALLOWSIGNATUREORIGINUNKNOWN = 0x2,
|
||||
MSIX_VALIDATION_OPTION_SKIPAPPXMANIFEST = 0x4
|
||||
} MSIX_VALIDATION_OPTION;
|
||||
|
||||
typedef /* [v1_enum] */
|
||||
enum APPX_PACKUNPACK_OPTION
|
||||
enum MSIX_PACKUNPACK_OPTION
|
||||
{
|
||||
APPX_PACKUNPACK_OPTION_NONE = 0x0,
|
||||
APPX_PACKUNPACK_OPTION_CREATEPACKAGESUBFOLDER = 0x1
|
||||
} APPX_PACKUNPACK_OPTION;
|
||||
MSIX_PACKUNPACK_OPTION_NONE = 0x0,
|
||||
MSIX_PACKUNPACK_OPTION_CREATEPACKAGESUBFOLDER = 0x1
|
||||
} MSIX_PACKUNPACK_OPTION;
|
||||
|
||||
// xPlatAppx specific
|
||||
|
||||
XPLATAPPX_API HRESULT STDMETHODCALLTYPE UnpackAppx(
|
||||
APPX_PACKUNPACK_OPTION packUnpackOptions,
|
||||
APPX_VALIDATION_OPTION validationOption,
|
||||
MSIX_API HRESULT STDMETHODCALLTYPE UnpackPackage(
|
||||
MSIX_PACKUNPACK_OPTION packUnpackOptions,
|
||||
MSIX_VALIDATION_OPTION validationOption,
|
||||
char* utf8SourcePackage,
|
||||
char* utf8Destination
|
||||
);
|
||||
|
@ -2017,26 +2017,26 @@ XPLATAPPX_API HRESULT STDMETHODCALLTYPE UnpackAppx(
|
|||
typedef LPVOID STDMETHODCALLTYPE COTASKMEMALLOC(SIZE_T cb);
|
||||
typedef void STDMETHODCALLTYPE COTASKMEMFREE(LPVOID pv);
|
||||
|
||||
XPLATAPPX_API HRESULT STDMETHODCALLTYPE GetLogTextUTF8(COTASKMEMALLOC* memalloc, char** logText);
|
||||
MSIX_API HRESULT STDMETHODCALLTYPE GetLogTextUTF8(COTASKMEMALLOC* memalloc, char** logText);
|
||||
|
||||
// Call specific for Windows. Default to call CoTaskMemAlloc and CoTaskMemFree
|
||||
XPLATAPPX_API HRESULT STDMETHODCALLTYPE CoCreateAppxFactory(
|
||||
APPX_VALIDATION_OPTION validationOption,
|
||||
MSIX_API HRESULT STDMETHODCALLTYPE CoCreateAppxFactory(
|
||||
MSIX_VALIDATION_OPTION validationOption,
|
||||
IAppxFactory** appxFactory);
|
||||
|
||||
XPLATAPPX_API HRESULT STDMETHODCALLTYPE CoCreateAppxFactoryWithHeap(
|
||||
MSIX_API HRESULT STDMETHODCALLTYPE CoCreateAppxFactoryWithHeap(
|
||||
COTASKMEMALLOC* memalloc,
|
||||
COTASKMEMFREE* memfree,
|
||||
APPX_VALIDATION_OPTION validationOption,
|
||||
MSIX_VALIDATION_OPTION validationOption,
|
||||
IAppxFactory** appxFactory);
|
||||
|
||||
// provided as a helper for platforms that do not have an implementation of SHCreateStreamOnFileEx
|
||||
XPLATAPPX_API HRESULT STDMETHODCALLTYPE CreateStreamOnFile(
|
||||
MSIX_API HRESULT STDMETHODCALLTYPE CreateStreamOnFile(
|
||||
char* utf8File,
|
||||
bool forRead,
|
||||
IStream** stream);
|
||||
|
||||
XPLATAPPX_API HRESULT STDMETHODCALLTYPE CreateStreamOnFileUTF16(
|
||||
MSIX_API HRESULT STDMETHODCALLTYPE CreateStreamOnFileUTF16(
|
||||
LPCWSTR utf16File,
|
||||
bool forRead,
|
||||
IStream** stream);
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
namespace xPlat {
|
||||
namespace MSIX {
|
||||
|
||||
enum class SignatureOrigin
|
||||
{
|
||||
|
@ -48,13 +48,13 @@ namespace xPlat {
|
|||
AXCI = 0x49435841, // AppxMetadata/CodeIntegrity.cat (uncompressed, optional)
|
||||
};
|
||||
|
||||
AppxSignatureObject(APPX_VALIDATION_OPTION validationOptions, IStream* stream);
|
||||
AppxSignatureObject(MSIX_VALIDATION_OPTION validationOptions, IStream* stream);
|
||||
|
||||
// IVerifierObject
|
||||
const std::string& GetPublisher() override { return m_publisher; }
|
||||
bool HasStream() override { return m_stream.Get() != nullptr; }
|
||||
xPlat::ComPtr<IStream> GetStream() override { return m_stream; }
|
||||
xPlat::ComPtr<IStream> GetValidationStream(const std::string& part, IStream* stream) override;
|
||||
MSIX::ComPtr<IStream> GetStream() override { return m_stream; }
|
||||
MSIX::ComPtr<IStream> GetValidationStream(const std::string& part, IStream* stream) override;
|
||||
|
||||
using Digest = std::vector<std::uint8_t>;
|
||||
|
||||
|
@ -69,8 +69,8 @@ namespace xPlat {
|
|||
bool m_hasDigests;
|
||||
std::map<DigestName, Digest> m_digests;
|
||||
SignatureOrigin m_signatureOrigin = SignatureOrigin::Unsigned; // assume unsigned until proven otherwise.
|
||||
APPX_VALIDATION_OPTION m_validationOptions;
|
||||
MSIX_VALIDATION_OPTION m_validationOptions;
|
||||
ComPtr<IStream> m_stream;
|
||||
std::string m_publisher;
|
||||
};
|
||||
} // namespace xPlat
|
||||
} // namespace MSIX
|
|
@ -1,6 +1,6 @@
|
|||
#pragma once
|
||||
#define NOMINMAX /* windows.h, or more correctly windef.h, defines min as a macro... */
|
||||
#include "AppxWindows.hpp"
|
||||
#include "MSIXWindows.hpp"
|
||||
#include "Exceptions.hpp"
|
||||
#include "StreamBase.hpp"
|
||||
#include "RangeStream.hpp"
|
||||
|
@ -15,7 +15,7 @@
|
|||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
namespace xPlat {
|
||||
namespace MSIX {
|
||||
|
||||
const std::uint64_t BLOCKMAP_BLOCK_SIZE = 65536; // 64KB
|
||||
|
||||
|
@ -36,7 +36,7 @@ namespace xPlat {
|
|||
class BlockMapStream : public StreamBase
|
||||
{
|
||||
public:
|
||||
BlockMapStream(IxPlatFactory* factory, std::string decodedName, IStream* stream, std::vector<Block>& blocks)
|
||||
BlockMapStream(IMSIXFactory* factory, std::string decodedName, IStream* stream, std::vector<Block>& blocks)
|
||||
: m_factory(factory), m_decodedName(decodedName), m_stream(stream)
|
||||
{
|
||||
// Determine overall stream size
|
||||
|
@ -163,6 +163,6 @@ namespace xPlat {
|
|||
std::uint64_t m_streamSize;
|
||||
std::string m_decodedName;
|
||||
ComPtr<IStream> m_stream;
|
||||
IxPlatFactory* m_factory;
|
||||
IMSIXFactory* m_factory;
|
||||
};
|
||||
}
|
|
@ -9,7 +9,7 @@
|
|||
#include "AppxPackaging.hpp"
|
||||
#include "xercesc/util/XMLString.hpp"
|
||||
|
||||
namespace xPlat {
|
||||
namespace MSIX {
|
||||
|
||||
template <typename ...Interfaces>
|
||||
struct QIHelper;
|
||||
|
@ -160,7 +160,7 @@ namespace xPlat {
|
|||
AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
throw xPlat::Exception(xPlat::Error::NoInterface);
|
||||
throw MSIX::Exception(MSIX::Error::NoInterface);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#include "StorageObject.hpp"
|
||||
#include "ComHelper.hpp"
|
||||
|
||||
namespace xPlat {
|
||||
namespace MSIX {
|
||||
|
||||
class DirectoryObject : public ComClass<DirectoryObject, IStorageObject>
|
||||
{
|
||||
|
@ -22,7 +22,7 @@ namespace xPlat {
|
|||
std::vector<std::string> GetFileNames(FileNameOptions options) override;
|
||||
IStream* GetFile(const std::string& fileName) override;
|
||||
void RemoveFile(const std::string& fileName) override;
|
||||
IStream* OpenFile(const std::string& fileName, xPlat::FileStream::Mode mode) override;
|
||||
IStream* OpenFile(const std::string& fileName, MSIX::FileStream::Mode mode) override;
|
||||
void CommitChanges() override;
|
||||
|
||||
protected:
|
||||
|
|
|
@ -7,13 +7,13 @@
|
|||
#include <functional>
|
||||
|
||||
#include "Log.hpp"
|
||||
#include "AppxWindows.hpp"
|
||||
#include "MSIXWindows.hpp"
|
||||
#include "xercesc/util/PlatformUtils.hpp"
|
||||
#include "xercesc/sax/ErrorHandler.hpp"
|
||||
#include "xercesc/sax/SAXParseException.hpp"
|
||||
#include "xercesc/dom/DOM.hpp"
|
||||
|
||||
namespace xPlat {
|
||||
namespace MSIX {
|
||||
|
||||
static const std::uint32_t ERROR_FACILITY = 0x8BAD0000; // Facility 2989
|
||||
static const std::uint32_t XERCES_SAX_FACILITY = ERROR_FACILITY + 0x1000; // Xerces XMLException. 0x8BAD1000 + XMLException error code
|
||||
|
@ -37,7 +37,7 @@ namespace xPlat {
|
|||
Stg_E_Invalidpointer = 0x80030009,
|
||||
|
||||
//
|
||||
// xPlat specific error codes
|
||||
// msix specific error codes
|
||||
//
|
||||
|
||||
// Basic file errors
|
||||
|
@ -62,18 +62,18 @@ namespace xPlat {
|
|||
InflateRead = ERROR_FACILITY + 0x0022,
|
||||
InflateCorruptData = ERROR_FACILITY + 0x0023,
|
||||
|
||||
// AppxPackage format errors
|
||||
AppxMissingSignatureP7X = ERROR_FACILITY + 0x0031,
|
||||
AppxMissingContentTypesXML = ERROR_FACILITY + 0x0032,
|
||||
AppxMissingBlockMapXML = ERROR_FACILITY + 0x0033,
|
||||
AppxMissingAppxManifestXML = ERROR_FACILITY + 0x0034,
|
||||
AppxDuplicateFootprintFile = ERROR_FACILITY + 0x0035,
|
||||
AppxUnknownFileNameEncoding = ERROR_FACILITY + 0x0036,
|
||||
// Package format errors
|
||||
MissingAppxSignatureP7X = ERROR_FACILITY + 0x0031,
|
||||
MissingContentTypesXML = ERROR_FACILITY + 0x0032,
|
||||
MissingAppxBlockMapXML = ERROR_FACILITY + 0x0033,
|
||||
MissingAppxManifestXML = ERROR_FACILITY + 0x0034,
|
||||
DuplicateFootprintFile = ERROR_FACILITY + 0x0035,
|
||||
UnknownFileNameEncoding = ERROR_FACILITY + 0x0036,
|
||||
|
||||
// Signature errors
|
||||
AppxSignatureInvalid = ERROR_FACILITY + 0x0041,
|
||||
AppxCertNotTrusted = ERROR_FACILITY + 0x0042,
|
||||
AppxPublisherMismatch = ERROR_FACILITY + 0x0043,
|
||||
SignatureInvalid = ERROR_FACILITY + 0x0041,
|
||||
CertNotTrusted = ERROR_FACILITY + 0x0042,
|
||||
PublisherMismatch = ERROR_FACILITY + 0x0043,
|
||||
|
||||
// Blockmap semantic errors
|
||||
BlockMapSemanticError = ERROR_FACILITY + 0x0051,
|
||||
|
@ -88,7 +88,7 @@ namespace xPlat {
|
|||
};
|
||||
|
||||
// Defines a common exception type to throw in exceptional cases. DO NOT USE FOR FLOW CONTROL!
|
||||
// Throwing xPlat::Exception will break into the debugger on chk builds to aid debugging
|
||||
// Throwing MSIX::Exception will break into the debugger on chk builds to aid debugging
|
||||
class Exception : public std::exception
|
||||
{
|
||||
public:
|
||||
|
@ -176,21 +176,21 @@ namespace xPlat {
|
|||
{
|
||||
// TODO: add message, line number and column
|
||||
assert(false);
|
||||
throw Exception(xPlat::Error::XercesWarning);
|
||||
throw Exception(MSIX::Error::XercesWarning);
|
||||
}
|
||||
|
||||
void error(const XERCES_CPP_NAMESPACE::SAXParseException& exp) override
|
||||
{
|
||||
// TODO: add message, line number and column
|
||||
assert(false);
|
||||
throw Exception(xPlat::Error::XercesError);
|
||||
throw Exception(MSIX::Error::XercesError);
|
||||
}
|
||||
|
||||
void fatalError(const XERCES_CPP_NAMESPACE::SAXParseException& exp) override
|
||||
{
|
||||
// TODO: add message, line number and column
|
||||
assert(false);
|
||||
throw Exception(xPlat::Error::XercesFatal);
|
||||
throw Exception(MSIX::Error::XercesFatal);
|
||||
}
|
||||
|
||||
void resetErrors() override {}
|
||||
|
@ -200,31 +200,31 @@ namespace xPlat {
|
|||
template <class Lambda>
|
||||
inline HRESULT ResultOf(Lambda lambda)
|
||||
{
|
||||
HRESULT hr = static_cast<HRESULT>(xPlat::Error::OK);
|
||||
HRESULT hr = static_cast<HRESULT>(MSIX::Error::OK);
|
||||
try
|
||||
{
|
||||
lambda();
|
||||
}
|
||||
catch (xPlat::Exception& e)
|
||||
catch (MSIX::Exception& e)
|
||||
{
|
||||
hr = static_cast<HRESULT>(e.Code());
|
||||
}
|
||||
catch (std::bad_alloc&)
|
||||
{
|
||||
hr = static_cast<HRESULT>(xPlat::Error::OutOfMemory);
|
||||
hr = static_cast<HRESULT>(MSIX::Error::OutOfMemory);
|
||||
}
|
||||
catch (std::exception&)
|
||||
{
|
||||
hr = static_cast<HRESULT>(xPlat::Error::Unexpected);
|
||||
hr = static_cast<HRESULT>(MSIX::Error::Unexpected);
|
||||
}
|
||||
catch (const XERCES_CPP_NAMESPACE::XMLException& e)
|
||||
{
|
||||
hr = static_cast<HRESULT>(xPlat::XERCES_XML_FACILITY) +
|
||||
hr = static_cast<HRESULT>(MSIX::XERCES_XML_FACILITY) +
|
||||
static_cast<HRESULT>(e.getCode());
|
||||
}
|
||||
catch (const XERCES_CPP_NAMESPACE::DOMException& e)
|
||||
{
|
||||
hr = static_cast<HRESULT>(xPlat::XERCES_DOM_FACILITY) +
|
||||
hr = static_cast<HRESULT>(MSIX::XERCES_DOM_FACILITY) +
|
||||
static_cast<HRESULT>(e.code);
|
||||
}
|
||||
|
||||
|
@ -238,7 +238,7 @@ namespace xPlat {
|
|||
if (!(a)) \
|
||||
{ \
|
||||
assert(false); \
|
||||
throw xPlat::Exception(c,m); \
|
||||
throw MSIX::Exception(c,m); \
|
||||
} \
|
||||
}
|
||||
|
||||
|
@ -247,7 +247,7 @@ namespace xPlat {
|
|||
if (!(a)) \
|
||||
{ \
|
||||
assert(false); \
|
||||
throw xPlat::Win32Exception(c,m); \
|
||||
throw MSIX::Win32Exception(c,m); \
|
||||
} \
|
||||
}
|
||||
|
||||
|
@ -258,6 +258,6 @@ namespace xPlat {
|
|||
HRESULT hr = a; \
|
||||
if (FAILED(hr)) \
|
||||
{ assert(false); \
|
||||
throw xPlat::Exception(hr, "COM Call failed"); \
|
||||
throw MSIX::Exception(hr, "COM Call failed"); \
|
||||
} \
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include "Exceptions.hpp"
|
||||
#include "StreamBase.hpp"
|
||||
|
||||
namespace xPlat {
|
||||
namespace MSIX {
|
||||
class FileStream : public StreamBase
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#pragma once
|
||||
#define NOMINMAX /* windows.h, or more correctly windef.h, defines min as a macro... */
|
||||
#include "AppxWindows.hpp"
|
||||
#include "MSIXWindows.hpp"
|
||||
#include "Exceptions.hpp"
|
||||
#include "StreamBase.hpp"
|
||||
#include "ComHelper.hpp"
|
||||
|
@ -11,7 +11,7 @@
|
|||
#include <functional>
|
||||
#include <algorithm>
|
||||
|
||||
namespace xPlat {
|
||||
namespace MSIX {
|
||||
|
||||
// This represents a subset of a Stream
|
||||
class HashStream : public StreamBase
|
||||
|
@ -49,16 +49,16 @@ namespace xPlat {
|
|||
m_cacheBuffer = std::make_unique<std::vector<std::uint8_t>>(m_streamSize);
|
||||
ULONG bytesRead = 0;
|
||||
ThrowHrIfFailed(m_stream->Read(m_cacheBuffer->data(), m_cacheBuffer->size(), &bytesRead));
|
||||
ThrowErrorIfNot(xPlat::Error::AppxSignatureInvalid, bytesRead == m_streamSize, "read failed");
|
||||
ThrowErrorIfNot(MSIX::Error::SignatureInvalid, bytesRead == m_streamSize, "read failed");
|
||||
|
||||
// compute digest and compare against expected digest
|
||||
std::vector<std::uint8_t> hash;
|
||||
ThrowErrorIfNot(xPlat::Error::AppxSignatureInvalid,
|
||||
xPlat::SHA256::ComputeHash(m_cacheBuffer->data(), m_cacheBuffer->size(), hash),
|
||||
ThrowErrorIfNot(MSIX::Error::SignatureInvalid,
|
||||
MSIX::SHA256::ComputeHash(m_cacheBuffer->data(), m_cacheBuffer->size(), hash),
|
||||
"Invalid signature");
|
||||
ThrowErrorIfNot(xPlat::Error::AppxSignatureInvalid, m_expectedHash.size() == hash.size(), "Signature is corrupt");
|
||||
ThrowErrorIfNot(MSIX::Error::SignatureInvalid, m_expectedHash.size() == hash.size(), "Signature is corrupt");
|
||||
ThrowErrorIfNot(
|
||||
xPlat::Error::AppxSignatureInvalid,
|
||||
MSIX::Error::SignatureInvalid,
|
||||
memcmp(m_expectedHash.data(), hash.data(), hash.size()) == 0,
|
||||
"Signature hash doesn't match digest hash"); //TODO: better exception
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#include <map>
|
||||
#include <functional>
|
||||
|
||||
namespace xPlat {
|
||||
namespace MSIX {
|
||||
|
||||
// This represents a LZW-compressed stream
|
||||
class InflateStream : public StreamBase
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
#include <string>
|
||||
|
||||
namespace xPlat {
|
||||
namespace MSIX {
|
||||
namespace Global {
|
||||
namespace Log {
|
||||
void Append(const std::string& comment);
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
#ifdef WIN32
|
||||
#define STDMETHODCALLTYPE __stdcall
|
||||
#define XPLATAPPX_API extern "C" __declspec(dllexport)
|
||||
#define MSIX_API extern "C" __declspec(dllexport)
|
||||
|
||||
// UNICODE MUST be defined before you include Windows.h if you want the non-ascii versions of APIs (and you do)
|
||||
#ifdef UNICODE
|
||||
|
@ -29,8 +29,8 @@
|
|||
#define STDMETHODCALLTYPE
|
||||
#endif
|
||||
|
||||
#undef XPLATAPPX_API
|
||||
#define XPLATAPPX_API extern "C"
|
||||
#undef MSIX_API
|
||||
#define MSIX_API extern "C"
|
||||
|
||||
#ifndef interface
|
||||
#define interface struct
|
|
@ -10,7 +10,7 @@
|
|||
#include "Exceptions.hpp"
|
||||
#include "StreamBase.hpp"
|
||||
|
||||
namespace xPlat {
|
||||
namespace MSIX {
|
||||
namespace Meta {
|
||||
|
||||
// Represents a heterogeneous collection of types that can be operated on as a compile-time vector
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include <functional>
|
||||
|
||||
|
||||
namespace xPlat {
|
||||
namespace MSIX {
|
||||
|
||||
// This represents a subset of a Stream
|
||||
class RangeStream : public StreamBase
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include <vector>
|
||||
|
||||
namespace xPlat {
|
||||
namespace MSIX {
|
||||
|
||||
const unsigned HASH_BYTES = 32;
|
||||
|
||||
|
|
|
@ -6,17 +6,17 @@
|
|||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
namespace xPlat {
|
||||
namespace MSIX {
|
||||
|
||||
typedef struct DigestHash
|
||||
{
|
||||
xPlat::AppxSignatureObject::DigestName name;
|
||||
MSIX::AppxSignatureObject::DigestName name;
|
||||
std::uint8_t content[HASH_BYTES];
|
||||
} DigestHash;
|
||||
|
||||
typedef struct DigestHeader
|
||||
{
|
||||
xPlat::AppxSignatureObject::DigestName name;
|
||||
MSIX::AppxSignatureObject::DigestName name;
|
||||
DigestHash hash[1];
|
||||
} DigestHeader;
|
||||
|
||||
|
@ -24,11 +24,11 @@ namespace xPlat {
|
|||
{
|
||||
public:
|
||||
static bool Validate(
|
||||
/*in*/ APPX_VALIDATION_OPTION option,
|
||||
/*in*/ IStream *stream,
|
||||
/*inout*/ std::map<xPlat::AppxSignatureObject::DigestName, xPlat::AppxSignatureObject::Digest>& digests,
|
||||
/*inout*/ SignatureOrigin& origin,
|
||||
/*inout*/ std::string& publisher);
|
||||
MSIX_VALIDATION_OPTION option,
|
||||
IStream *stream,
|
||||
std::map<MSIX::AppxSignatureObject::DigestName, MSIX::AppxSignatureObject::Digest>& digests,
|
||||
SignatureOrigin& origin,
|
||||
std::string& publisher);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ public:
|
|||
// Opens a stream to a file by name in the storage object. If the file does not exist and mode is read,
|
||||
// or read + update, then nullptr is returned. If the file is opened with write and it does not exist,
|
||||
// then the file is created and an empty stream to the file is handed back to the caller.
|
||||
virtual IStream* OpenFile(const std::string& fileName, xPlat::FileStream::Mode mode) = 0;
|
||||
virtual IStream* OpenFile(const std::string& fileName, MSIX::FileStream::Mode mode) = 0;
|
||||
|
||||
// Some storage objects may operate under cache semantics and therefore require an explicit commit.
|
||||
// Clients should explicitly call CommitChanges after all write operations into the object are complete.
|
||||
|
|
|
@ -6,13 +6,13 @@
|
|||
#include <iostream>
|
||||
#include <limits>
|
||||
|
||||
#include "AppxWindows.hpp"
|
||||
#include "MSIXWindows.hpp"
|
||||
#include "AppxPackaging.hpp"
|
||||
#include "Exceptions.hpp"
|
||||
#include "ComHelper.hpp"
|
||||
|
||||
namespace xPlat {
|
||||
class StreamBase : public xPlat::ComClass<StreamBase, IAppxFile, IStream>
|
||||
namespace MSIX {
|
||||
class StreamBase : public MSIX::ComClass<StreamBase, IAppxFile, IStream>
|
||||
{
|
||||
public:
|
||||
// These are the same values as STREAM_SEEK. See
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
namespace xPlat {
|
||||
namespace MSIX {
|
||||
|
||||
// converts an input utf8 formatted string into a utf16 formatted string
|
||||
std::wstring utf8_to_utf16(const std::string& utf8string);
|
||||
|
@ -10,4 +10,4 @@ namespace xPlat {
|
|||
// converts an input utf16 formatted string into a utf8 formatted string
|
||||
std::string utf16_to_utf8(const std::wstring& utf16string);
|
||||
|
||||
} // namespace xPlat
|
||||
} // namespace MSIX
|
|
@ -5,7 +5,7 @@
|
|||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
namespace xPlat {
|
||||
namespace MSIX {
|
||||
|
||||
class VectorStream : public StreamBase
|
||||
{
|
||||
|
@ -47,4 +47,4 @@ namespace xPlat {
|
|||
ULONG m_offset = 0;
|
||||
std::vector<std::uint8_t>* m_data;
|
||||
};
|
||||
} // namespace xPlat
|
||||
} // namespace MSIX
|
|
@ -21,8 +21,8 @@ class IVerifierObject : public IUnknown
|
|||
public:
|
||||
virtual const std::string& GetPublisher() = 0;
|
||||
virtual bool HasStream() = 0;
|
||||
virtual xPlat::ComPtr<IStream> GetStream() = 0;
|
||||
virtual xPlat::ComPtr<IStream> GetValidationStream(const std::string& part, IStream* stream) = 0;
|
||||
virtual MSIX::ComPtr<IStream> GetStream() = 0;
|
||||
virtual MSIX::ComPtr<IStream> GetValidationStream(const std::string& part, IStream* stream) = 0;
|
||||
};
|
||||
|
||||
SpecializeUuidOfImpl(IVerifierObject);
|
|
@ -35,7 +35,7 @@ public:
|
|||
|
||||
SpecializeUuidOfImpl(IXmlObject);
|
||||
|
||||
namespace xPlat {
|
||||
namespace MSIX {
|
||||
|
||||
// XML de-serialization happens during construction, of this object.
|
||||
// XML serialization happens through the Write method
|
||||
|
@ -108,8 +108,8 @@ namespace xPlat {
|
|||
// IVerifierObject
|
||||
const std::string& GetPublisher() override { throw Exception(Error::NotSupported); }
|
||||
bool HasStream() override { return m_stream.Get() != nullptr; }
|
||||
xPlat::ComPtr<IStream> GetStream() override { return m_stream; }
|
||||
xPlat::ComPtr<IStream> GetValidationStream(const std::string& part, IStream* stream) override
|
||||
MSIX::ComPtr<IStream> GetStream() override { return m_stream; }
|
||||
MSIX::ComPtr<IStream> GetValidationStream(const std::string& part, IStream* stream) override
|
||||
{
|
||||
throw Exception(Error::NotSupported);
|
||||
}
|
||||
|
@ -119,4 +119,4 @@ namespace xPlat {
|
|||
ComPtr<IStream> m_stream;
|
||||
};
|
||||
|
||||
} // namespace xPlat
|
||||
} // namespace MSIX
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
namespace xPlat {
|
||||
namespace MSIX {
|
||||
|
||||
// This represents a raw stream over a file contained in a .zip file.
|
||||
class ZipFileStream : public RangeStream
|
||||
|
@ -17,7 +17,7 @@ namespace xPlat {
|
|||
ZipFileStream(
|
||||
std::string name,
|
||||
std::string contentType,
|
||||
IxPlatFactory* factory,
|
||||
IMSIXFactory* factory,
|
||||
bool isCompressed,
|
||||
std::uint64_t offset,
|
||||
std::uint64_t size,
|
||||
|
@ -45,7 +45,7 @@ namespace xPlat {
|
|||
inline bool IsCompressed() { return m_isCompressed; }
|
||||
|
||||
protected:
|
||||
IxPlatFactory* m_factory;
|
||||
IMSIXFactory* m_factory;
|
||||
std::string m_name;
|
||||
std::string m_contentType;
|
||||
bool m_isCompressed = false;
|
||||
|
|
|
@ -10,23 +10,23 @@
|
|||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
namespace xPlat {
|
||||
namespace MSIX {
|
||||
// This represents a raw stream over a.zip file.
|
||||
class ZipObject : public ComClass<ZipObject, IStorageObject>
|
||||
{
|
||||
public:
|
||||
ZipObject(IxPlatFactory* appxFactory, IStream* stream);
|
||||
ZipObject(IMSIXFactory* factory, IStream* stream);
|
||||
|
||||
// StorageObject methods
|
||||
std::string GetPathSeparator() override;
|
||||
std::vector<std::string> GetFileNames(FileNameOptions options) override;
|
||||
IStream* GetFile(const std::string& fileName) override;
|
||||
void RemoveFile(const std::string& fileName) override;
|
||||
IStream* OpenFile(const std::string& fileName, xPlat::FileStream::Mode mode) override;
|
||||
IStream* OpenFile(const std::string& fileName, MSIX::FileStream::Mode mode) override;
|
||||
void CommitChanges() override;
|
||||
|
||||
protected:
|
||||
IxPlatFactory* m_factory;
|
||||
IMSIXFactory* m_factory;
|
||||
ComPtr<IStream> m_stream;
|
||||
std::map<std::string, ComPtr<IStream>> m_streams;
|
||||
};//class ZipObject
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
# xplat\src\MakeXplat
|
||||
# MSIX\src\makemsix
|
||||
# Copyright (C) 2017 Microsoft
|
||||
# Created by Phil Smith (psmith@microsoft.com) on 10/19/2017
|
||||
|
||||
cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR)
|
||||
project (MakeXplat)
|
||||
|
||||
cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR)
|
||||
project (makemsix)
|
||||
|
||||
# Define two variables in order not to repeat ourselves.
|
||||
set(BINARY_NAME MakeXplat)
|
||||
|
||||
set(BINARY_NAME makemsix)
|
||||
|
||||
include_directories(
|
||||
${include_directories}
|
||||
${CMAKE_PROJECT_ROOT}/src/inc
|
||||
|
@ -16,9 +16,9 @@ include_directories(
|
|||
add_executable(${BINARY_NAME}
|
||||
main.cpp
|
||||
)
|
||||
|
||||
# specify that this binary is to be built with C++14
|
||||
|
||||
# specify that this binary is to be built with C++14
|
||||
set_property(TARGET ${BINARY_NAME} PROPERTY CXX_STANDARD 14)
|
||||
|
||||
ADD_DEPENDENCIES(${BINARY_NAME} xPlatAppx)
|
||||
target_link_libraries(${BINARY_NAME} xPlatAppx)
|
||||
ADD_DEPENDENCIES(${BINARY_NAME} msix)
|
||||
target_link_libraries(${BINARY_NAME} msix)
|
|
@ -1,4 +1,4 @@
|
|||
#include "AppxWindows.hpp"
|
||||
#include "MSIXWindows.hpp"
|
||||
#include "AppxPackaging.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
@ -33,25 +33,25 @@ struct State
|
|||
|
||||
bool CreatePackageSubfolder()
|
||||
{
|
||||
unpackOptions = static_cast<APPX_PACKUNPACK_OPTION>(unpackOptions | APPX_PACKUNPACK_OPTION::APPX_PACKUNPACK_OPTION_CREATEPACKAGESUBFOLDER);
|
||||
unpackOptions = static_cast<MSIX_PACKUNPACK_OPTION>(unpackOptions | MSIX_PACKUNPACK_OPTION::MSIX_PACKUNPACK_OPTION_CREATEPACKAGESUBFOLDER);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SkipManifestValidation()
|
||||
{
|
||||
validationOptions = static_cast<APPX_VALIDATION_OPTION>(validationOptions | APPX_VALIDATION_OPTION::APPX_VALIDATION_OPTION_SKIPAPPXMANIFEST);
|
||||
validationOptions = static_cast<MSIX_VALIDATION_OPTION>(validationOptions | MSIX_VALIDATION_OPTION::MSIX_VALIDATION_OPTION_SKIPAPPXMANIFEST);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SkipSignature()
|
||||
{
|
||||
validationOptions = static_cast<APPX_VALIDATION_OPTION>(validationOptions | APPX_VALIDATION_OPTION::APPX_VALIDATION_OPTION_SKIPSIGNATURE);
|
||||
validationOptions = static_cast<MSIX_VALIDATION_OPTION>(validationOptions | MSIX_VALIDATION_OPTION::MSIX_VALIDATION_OPTION_SKIPSIGNATURE);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AllowSignatureOriginUnknown()
|
||||
{
|
||||
validationOptions = static_cast<APPX_VALIDATION_OPTION>(validationOptions | APPX_VALIDATION_OPTION::APPX_VALIDATION_OPTION_ALLOWSIGNATUREORIGINUNKNOWN);
|
||||
validationOptions = static_cast<MSIX_VALIDATION_OPTION>(validationOptions | MSIX_VALIDATION_OPTION::MSIX_VALIDATION_OPTION_ALLOWSIGNATUREORIGINUNKNOWN);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -73,8 +73,8 @@ struct State
|
|||
std::string certName;
|
||||
std::string directoryName;
|
||||
UserSpecified specified = UserSpecified::Nothing;
|
||||
APPX_VALIDATION_OPTION validationOptions = APPX_VALIDATION_OPTION::APPX_VALIDATION_OPTION_FULL;
|
||||
APPX_PACKUNPACK_OPTION unpackOptions = APPX_PACKUNPACK_OPTION::APPX_PACKUNPACK_OPTION_NONE;
|
||||
MSIX_VALIDATION_OPTION validationOptions = MSIX_VALIDATION_OPTION::MSIX_VALIDATION_OPTION_FULL;
|
||||
MSIX_PACKUNPACK_OPTION unpackOptions = MSIX_PACKUNPACK_OPTION::MSIX_PACKUNPACK_OPTION_NONE;
|
||||
};
|
||||
|
||||
// describes an option to a command that the user may specify
|
||||
|
@ -205,7 +205,7 @@ int ParseAndRun(std::map<std::string, Command>& commands, State& state, int argc
|
|||
Error(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
return UnpackAppx(state.unpackOptions, state.validationOptions,
|
||||
return UnpackPackage(state.unpackOptions, state.validationOptions,
|
||||
const_cast<char*>(state.packageName.c_str()),
|
||||
const_cast<char*>(state.directoryName.c_str())
|
||||
);
|
|
@ -28,7 +28,7 @@
|
|||
|
||||
XERCES_CPP_NAMESPACE_USE
|
||||
|
||||
namespace xPlat {
|
||||
namespace MSIX {
|
||||
|
||||
static std::uint32_t GetLocalFileHeaderSize(XERCES_CPP_NAMESPACE::DOMElement* element)
|
||||
{
|
||||
|
@ -82,7 +82,7 @@ namespace xPlat {
|
|||
return result;
|
||||
}
|
||||
|
||||
AppxBlockMapObject::AppxBlockMapObject(IxPlatFactory* factory, ComPtr<IStream>& stream) : m_factory(factory), m_stream(stream)
|
||||
AppxBlockMapObject::AppxBlockMapObject(IMSIXFactory* factory, ComPtr<IStream>& stream) : m_factory(factory), m_stream(stream)
|
||||
{
|
||||
auto dom = ComPtr<IXmlObject>::Make<XmlObject>(stream, &blockMapSchema);
|
||||
// Create xPath query over blockmap file.
|
||||
|
@ -135,7 +135,7 @@ namespace xPlat {
|
|||
}
|
||||
}
|
||||
|
||||
xPlat::ComPtr<IStream> AppxBlockMapObject::GetValidationStream(const std::string& part, IStream* stream)
|
||||
MSIX::ComPtr<IStream> AppxBlockMapObject::GetValidationStream(const std::string& part, IStream* stream)
|
||||
{
|
||||
ThrowErrorIf(Error::InvalidParameter, (part.empty() || stream == nullptr), "bad input");
|
||||
auto item = m_blockMap.find(part);
|
||||
|
@ -207,6 +207,6 @@ namespace xPlat {
|
|||
}
|
||||
|
||||
void AppxBlockMapObject::RemoveFile(const std::string& ) { throw Exception(Error::NotImplemented); }
|
||||
IStream* AppxBlockMapObject::OpenFile(const std::string& ,xPlat::FileStream::Mode) { throw Exception(Error::NotImplemented); }
|
||||
IStream* AppxBlockMapObject::OpenFile(const std::string& ,MSIX::FileStream::Mode) { throw Exception(Error::NotImplemented); }
|
||||
void AppxBlockMapObject::CommitChanges() { throw Exception(Error::NotImplemented); }
|
||||
}
|
|
@ -4,7 +4,7 @@
|
|||
#include "ZipObject.hpp"
|
||||
#include "AppxPackageObject.hpp"
|
||||
|
||||
namespace xPlat {
|
||||
namespace MSIX {
|
||||
// IAppxFactory
|
||||
HRESULT STDMETHODCALLTYPE AppxFactory::CreatePackageWriter (
|
||||
IStream* outputStream,
|
||||
|
@ -20,8 +20,8 @@ namespace xPlat {
|
|||
{
|
||||
return ResultOf([&]() {
|
||||
ThrowErrorIf(Error::InvalidParameter, (packageReader == nullptr || *packageReader != nullptr), "Invalid parameter");
|
||||
ComPtr<IxPlatFactory> self;
|
||||
ThrowHrIfFailed(QueryInterface(UuidOfImpl<IxPlatFactory>::iid, reinterpret_cast<void**>(&self)));
|
||||
ComPtr<IMSIXFactory> self;
|
||||
ThrowHrIfFailed(QueryInterface(UuidOfImpl<IMSIXFactory>::iid, reinterpret_cast<void**>(&self)));
|
||||
auto zip = ComPtr<IStorageObject>::Make<ZipObject>(self.Get(), inputStream);
|
||||
auto result = ComPtr<IAppxPackageReader>::Make<AppxPackageObject>(self.Get(), m_validationOptions, zip.Get());
|
||||
*packageReader = result.Detach();
|
||||
|
@ -49,8 +49,8 @@ namespace xPlat {
|
|||
*blockMapReader != nullptr
|
||||
),"bad pointer.");
|
||||
|
||||
ComPtr<IxPlatFactory> self;
|
||||
ThrowHrIfFailed(QueryInterface(UuidOfImpl<IxPlatFactory>::iid, reinterpret_cast<void**>(&self)));
|
||||
ComPtr<IMSIXFactory> self;
|
||||
ThrowHrIfFailed(QueryInterface(UuidOfImpl<IMSIXFactory>::iid, reinterpret_cast<void**>(&self)));
|
||||
ComPtr<IStream> stream(inputStream);
|
||||
*blockMapReader = ComPtr<IAppxBlockMapReader>::Make<AppxBlockMapObject>(self.Get(), stream).Detach();
|
||||
});
|
||||
|
@ -70,8 +70,8 @@ namespace xPlat {
|
|||
*blockMapReader != nullptr
|
||||
),"bad pointer.");
|
||||
|
||||
ComPtr<IxPlatFactory> self;
|
||||
ThrowHrIfFailed(QueryInterface(UuidOfImpl<IxPlatFactory>::iid, reinterpret_cast<void**>(&self)));
|
||||
ComPtr<IMSIXFactory> self;
|
||||
ThrowHrIfFailed(QueryInterface(UuidOfImpl<IMSIXFactory>::iid, reinterpret_cast<void**>(&self)));
|
||||
auto stream = ComPtr<IStream>::Make<FileStream>(utf16_to_utf8(signatureFileName), FileStream::Mode::READ);
|
||||
auto signature = ComPtr<IVerifierObject>::Make<AppxSignatureObject>(self->GetValidationOptions(), stream.Get());
|
||||
auto validatedStream = signature->GetValidationStream("AppxBlockMap.xml", inputStream);
|
||||
|
@ -107,4 +107,4 @@ namespace xPlat {
|
|||
});
|
||||
}
|
||||
|
||||
} // namespace xPlat
|
||||
} // namespace MSIX
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
XERCES_CPP_NAMESPACE_USE
|
||||
|
||||
namespace xPlat {
|
||||
namespace MSIX {
|
||||
|
||||
// names of footprint files.
|
||||
#define APPXBLOCKMAP_XML "AppxBlockMap.xml"
|
||||
|
@ -88,7 +88,7 @@ namespace xPlat {
|
|||
{ result += found->second;
|
||||
}
|
||||
else
|
||||
{ throw Exception(Error::AppxUnknownFileNameEncoding, fileName);
|
||||
{ throw Exception(Error::UnknownFileNameEncoding, fileName);
|
||||
}
|
||||
i += 2;
|
||||
}
|
||||
|
@ -150,7 +150,7 @@ namespace xPlat {
|
|||
m_packageId = std::make_unique<AppxPackageId>(name, version, resourceId, architecture, publisher);
|
||||
}
|
||||
|
||||
AppxPackageObject::AppxPackageObject(IxPlatFactory* factory, APPX_VALIDATION_OPTION validation, IStorageObject* container) :
|
||||
AppxPackageObject::AppxPackageObject(IMSIXFactory* factory, MSIX_VALIDATION_OPTION validation, IStorageObject* container) :
|
||||
m_factory(factory),
|
||||
m_validation(validation),
|
||||
m_container(container)
|
||||
|
@ -158,39 +158,39 @@ namespace xPlat {
|
|||
// 1. Get the appx signature from the container and parse it
|
||||
// TODO: pass validation flags and other necessary goodness through.
|
||||
m_appxSignature = ComPtr<IVerifierObject>::Make<AppxSignatureObject>(validation,
|
||||
((validation & APPX_VALIDATION_OPTION_SKIPSIGNATURE) == 0) ? m_container->GetFile(APPXSIGNATURE_P7X) : nullptr
|
||||
((validation & MSIX_VALIDATION_OPTION_SKIPSIGNATURE) == 0) ? m_container->GetFile(APPXSIGNATURE_P7X) : nullptr
|
||||
);
|
||||
|
||||
if ((validation & APPX_VALIDATION_OPTION_SKIPSIGNATURE) == 0)
|
||||
{ ThrowErrorIfNot(Error::AppxMissingSignatureP7X, (m_appxSignature->HasStream()), "AppxSignature.p7x not in archive!");
|
||||
if ((validation & MSIX_VALIDATION_OPTION_SKIPSIGNATURE) == 0)
|
||||
{ ThrowErrorIfNot(Error::MissingAppxSignatureP7X, (m_appxSignature->HasStream()), "AppxSignature.p7x not in archive!");
|
||||
}
|
||||
|
||||
// 2. Get content type using signature object for validation
|
||||
// TODO: switch underlying type of m_contentType to something more specific.
|
||||
auto temp = m_appxSignature->GetValidationStream(CONTENT_TYPES_XML, m_container->GetFile(CONTENT_TYPES_XML));
|
||||
m_contentType = ComPtr<IVerifierObject>::Make<XmlObject>(temp, &contentTypesSchema);
|
||||
ThrowErrorIfNot(Error::AppxMissingContentTypesXML, (m_contentType->HasStream()), "[Content_Types].xml not in archive!");
|
||||
ThrowErrorIfNot(Error::MissingContentTypesXML, (m_contentType->HasStream()), "[Content_Types].xml not in archive!");
|
||||
|
||||
// 3. Get blockmap object using signature object for validation
|
||||
temp = m_appxSignature->GetValidationStream(APPXBLOCKMAP_XML, m_container->GetFile(APPXBLOCKMAP_XML));
|
||||
m_appxBlockMap = ComPtr<IVerifierObject>::Make<AppxBlockMapObject>(factory, temp);
|
||||
ThrowErrorIfNot(Error::AppxMissingBlockMapXML, (m_appxBlockMap->HasStream()), "AppxBlockMap.xml not in archive!");
|
||||
ThrowErrorIfNot(Error::MissingAppxBlockMapXML, (m_appxBlockMap->HasStream()), "AppxBlockMap.xml not in archive!");
|
||||
|
||||
// 4. Get manifest object using blockmap object for validation
|
||||
// TODO: pass validation flags and other necessary goodness through.
|
||||
temp = m_appxBlockMap->GetValidationStream(APPXMANIFEST_XML, m_container->GetFile(APPXMANIFEST_XML));
|
||||
m_appxManifest = ComPtr<IVerifierObject>::Make<AppxManifestObject>(temp);
|
||||
ThrowErrorIfNot(Error::AppxMissingAppxManifestXML, (m_appxBlockMap->HasStream()), "AppxManifest.xml not in archive!");
|
||||
if ((validation & APPX_VALIDATION_OPTION_SKIPSIGNATURE) == 0)
|
||||
ThrowErrorIfNot(Error::MissingAppxManifestXML, (m_appxBlockMap->HasStream()), "AppxManifest.xml not in archive!");
|
||||
if ((validation & MSIX_VALIDATION_OPTION_SKIPSIGNATURE) == 0)
|
||||
{
|
||||
std::string reason = "Publisher mismatch: '" + m_appxManifest->GetPublisher() + "' != '" + m_appxSignature->GetPublisher() + "'";
|
||||
ThrowErrorIfNot(Error::AppxPublisherMismatch,
|
||||
ThrowErrorIfNot(Error::PublisherMismatch,
|
||||
(0 == m_appxManifest->GetPublisher().compare(m_appxSignature->GetPublisher())), reason);
|
||||
}
|
||||
|
||||
struct Config
|
||||
{
|
||||
using lambda = std::function<xPlat::ComPtr<IStream>()>;
|
||||
using lambda = std::function<MSIX::ComPtr<IStream>()>;
|
||||
Config(lambda f) : GetValidationStream(f) {}
|
||||
lambda GetValidationStream;
|
||||
};
|
||||
|
@ -230,19 +230,13 @@ namespace xPlat {
|
|||
ThrowErrorIfNot(Error::BlockMapSemanticError, (filesToProcess.empty()), "Package not valid!");
|
||||
}
|
||||
|
||||
void AppxPackageObject::Pack(APPX_PACKUNPACK_OPTION options, const std::string& certFile, IStorageObject* from)
|
||||
{
|
||||
// TODO: Implement
|
||||
throw Exception(Error::NotImplemented);
|
||||
}
|
||||
|
||||
void AppxPackageObject::Unpack(APPX_PACKUNPACK_OPTION options, IStorageObject* to)
|
||||
void AppxPackageObject::Unpack(MSIX_PACKUNPACK_OPTION options, IStorageObject* to)
|
||||
{
|
||||
auto fileNames = GetFileNames(FileNameOptions::All);
|
||||
for (const auto& fileName : fileNames)
|
||||
{
|
||||
std::string targetName;
|
||||
if (options & APPX_PACKUNPACK_OPTION_CREATEPACKAGESUBFOLDER)
|
||||
if (options & MSIX_PACKUNPACK_OPTION_CREATEPACKAGESUBFOLDER)
|
||||
{ throw Exception(Error::NotImplemented);
|
||||
//targetName = GetAppxManifest()->GetPackageFullName() + to->GetPathSeparator() + fileName;
|
||||
}
|
||||
|
@ -250,7 +244,7 @@ namespace xPlat {
|
|||
{ targetName = DecodeFileName(fileName);
|
||||
}
|
||||
|
||||
auto targetFile = to->OpenFile(targetName, xPlat::FileStream::Mode::WRITE_UPDATE);
|
||||
auto targetFile = to->OpenFile(targetName, MSIX::FileStream::Mode::WRITE_UPDATE);
|
||||
auto sourceFile = GetFile(fileName);
|
||||
|
||||
ULARGE_INTEGER bytesCount = {0};
|
||||
|
@ -288,7 +282,7 @@ namespace xPlat {
|
|||
throw Exception(Error::NotImplemented);
|
||||
}
|
||||
|
||||
IStream* AppxPackageObject::OpenFile(const std::string& fileName, xPlat::FileStream::Mode mode)
|
||||
IStream* AppxPackageObject::OpenFile(const std::string& fileName, MSIX::FileStream::Mode mode)
|
||||
{
|
||||
// TODO: Implement
|
||||
throw Exception(Error::NotImplemented);
|
||||
|
@ -303,7 +297,7 @@ namespace xPlat {
|
|||
// IAppxPackageReader
|
||||
HRESULT STDMETHODCALLTYPE AppxPackageObject::GetBlockMap(IAppxBlockMapReader** blockMapReader)
|
||||
{
|
||||
return xPlat::ResultOf([&]() {
|
||||
return MSIX::ResultOf([&]() {
|
||||
// TODO: Implement
|
||||
throw Exception(Error::NotImplemented);
|
||||
});
|
||||
|
@ -311,7 +305,7 @@ namespace xPlat {
|
|||
|
||||
HRESULT STDMETHODCALLTYPE AppxPackageObject::GetFootprintFile(APPX_FOOTPRINT_FILE_TYPE type, IAppxFile** file)
|
||||
{
|
||||
return xPlat::ResultOf([&]() {
|
||||
return MSIX::ResultOf([&]() {
|
||||
ThrowErrorIf(Error::InvalidParameter, (file == nullptr || *file != nullptr), "bad pointer");
|
||||
auto footprint = footprintFiles.find(type);
|
||||
ThrowErrorIf(Error::FileNotFound, (footprint == footprintFiles.end()), "unknown footprint file type");
|
||||
|
@ -326,7 +320,7 @@ namespace xPlat {
|
|||
|
||||
HRESULT STDMETHODCALLTYPE AppxPackageObject::GetPayloadFile(LPCWSTR fileName, IAppxFile** file)
|
||||
{
|
||||
return xPlat::ResultOf([&]() {
|
||||
return MSIX::ResultOf([&]() {
|
||||
ThrowErrorIf(Error::InvalidParameter, (fileName == nullptr || file == nullptr || *file != nullptr), "bad pointer");
|
||||
std::string name = utf16_to_utf8(fileName);
|
||||
ComPtr<IStream> stream = GetFile(name);
|
||||
|
@ -340,7 +334,7 @@ namespace xPlat {
|
|||
|
||||
HRESULT STDMETHODCALLTYPE AppxPackageObject::GetPayloadFiles(IAppxFilesEnumerator** filesEnumerator)
|
||||
{
|
||||
return xPlat::ResultOf([&]() {
|
||||
return MSIX::ResultOf([&]() {
|
||||
ThrowErrorIf(Error::InvalidParameter,(filesEnumerator == nullptr || *filesEnumerator != nullptr), "bad pointer");
|
||||
|
||||
ComPtr<IStorageObject> storage;
|
||||
|
@ -352,7 +346,7 @@ namespace xPlat {
|
|||
|
||||
HRESULT STDMETHODCALLTYPE AppxPackageObject::GetManifest(IAppxManifestReader** manifestReader)
|
||||
{
|
||||
return xPlat::ResultOf([&]() {
|
||||
return MSIX::ResultOf([&]() {
|
||||
// TODO: Implement
|
||||
throw Exception(Error::NotImplemented);
|
||||
});
|
|
@ -96,9 +96,9 @@ MIDL_DEFINE_GUID(IID, IID_IAppxEncryptedBundleWriter2,0xE644BE82,0xF0FA,0x42B8,0
|
|||
//MIDL_DEFINE_GUID(IID, IID_IAppxPackageEditor,0xE2ADB6DC,0x5E71,0x4416,0x86,0xB6,0x86,0xE5,0xF5,0x29,0x1A,0x6B);
|
||||
|
||||
// internal interfaces.
|
||||
MIDL_DEFINE_GUID(IID, IID_IAppxPackage, 0x51B2C456,0xAAA9,0x46D6,0x8E,0xC9,0x29,0x82,0x20,0x55,0x91,0x89);
|
||||
MIDL_DEFINE_GUID(IID, IID_IPackage, 0x51B2C456,0xAAA9,0x46D6,0x8E,0xC9,0x29,0x82,0x20,0x55,0x91,0x89);
|
||||
MIDL_DEFINE_GUID(IID, IID_IStorageObject, 0xEC25B96E,0x0DB1,0x4483,0xBD,0xB1,0xCA,0xB1,0x10,0x9C,0xB7,0x41);
|
||||
MIDL_DEFINE_GUID(IID, IID_IxPlatFactory, 0x1f850db4,0x32b8,0x4db6,0x8b,0xf4,0x5a,0x89,0x7e,0xb6,0x11,0xf1);
|
||||
MIDL_DEFINE_GUID(IID, IID_IMSIXFactory, 0x1f850db4,0x32b8,0x4db6,0x8b,0xf4,0x5a,0x89,0x7e,0xb6,0x11,0xf1);
|
||||
MIDL_DEFINE_GUID(IID, IID_IVerifierObject, 0xcb0a105c,0x3a6c,0x4e48,0x93,0x51,0x37,0x7c,0x4d,0xcc,0xd8,0x90);
|
||||
MIDL_DEFINE_GUID(IID, IID_IXmlObject, 0x0e7a446e,0xbaf7,0x44c1,0xb3,0x8a,0x21,0x6b,0xfa,0x18,0xa1,0xa8);
|
||||
#undef MIDL_DEFINE_GUID
|
|
@ -1,4 +1,4 @@
|
|||
#include "AppxWindows.hpp"
|
||||
#include "MSIXWindows.hpp"
|
||||
#include "Exceptions.hpp"
|
||||
#include "StreamBase.hpp"
|
||||
#include "StorageObject.hpp"
|
||||
|
@ -15,22 +15,22 @@
|
|||
#include <functional>
|
||||
#include <set>
|
||||
|
||||
namespace xPlat {
|
||||
namespace MSIX {
|
||||
|
||||
AppxSignatureObject::AppxSignatureObject(APPX_VALIDATION_OPTION validationOptions, IStream* stream) :
|
||||
AppxSignatureObject::AppxSignatureObject(MSIX_VALIDATION_OPTION validationOptions, IStream* stream) :
|
||||
m_stream(stream),
|
||||
m_validationOptions(validationOptions)
|
||||
{
|
||||
m_hasDigests = SignatureValidator::Validate(validationOptions, stream, m_digests, m_signatureOrigin, m_publisher);
|
||||
|
||||
if (0 == (validationOptions & APPX_VALIDATION_OPTION::APPX_VALIDATION_OPTION_SKIPSIGNATURE))
|
||||
if (0 == (validationOptions & MSIX_VALIDATION_OPTION::MSIX_VALIDATION_OPTION_SKIPSIGNATURE))
|
||||
{ // reset the source stream back to the beginning after validating it.
|
||||
LARGE_INTEGER li{0};
|
||||
ThrowHrIfFailed(stream->Seek(li, StreamBase::Reference::START, nullptr));
|
||||
}
|
||||
}
|
||||
|
||||
xPlat::ComPtr<IStream> AppxSignatureObject::GetValidationStream(const std::string& part, IStream* stream)
|
||||
MSIX::ComPtr<IStream> AppxSignatureObject::GetValidationStream(const std::string& part, IStream* stream)
|
||||
{
|
||||
if (m_hasDigests)
|
||||
{
|
||||
|
@ -51,4 +51,4 @@ xPlat::ComPtr<IStream> AppxSignatureObject::GetValidationStream(const std::stri
|
|||
return stream;
|
||||
}
|
||||
|
||||
} // namespace xPlat
|
||||
} // namespace MSIX
|
|
@ -1,17 +1,17 @@
|
|||
# xplat\src\xPlatAppx
|
||||
# MSIX\src\msix
|
||||
# Copyright (C) 2017 Microsoft
|
||||
# Created by Phil Smith (psmith@microsoft.com) on 10/19/2017
|
||||
|
||||
cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR)
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/../../cmake) # main (top) cmake dir
|
||||
|
||||
set(LIBRARY_NAME xPlatAppx)
|
||||
set(LIBRARY_NAME msix)
|
||||
|
||||
project(${LIBRARY_NAME})
|
||||
|
||||
# Define PALs
|
||||
IF(WIN32)
|
||||
set (XPLATAPPX_API=1)
|
||||
set (MSIX_API=1)
|
||||
set (DirectoryObject PAL/FileSystem/Win32/DirectoryObject.cpp)
|
||||
set (SHA256 PAL/SHA256/Win32/SHA256.cpp)
|
||||
set (Signature PAL/Signature/Win32/SignatureValidator.cpp)
|
||||
|
@ -22,11 +22,11 @@ ELSE()
|
|||
set(CMAKE_VISIBILITY_INLINES_HIDDEN 1)
|
||||
set(CMAKE_C_VISIBILITY_PRESET hidden)
|
||||
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
|
||||
set(DEFINE_EXPORTS "-exported_symbols_list ${CMAKE_PROJECT_ROOT}/src/xPlatAppx/exports.def")
|
||||
set(DEFINE_EXPORTS "-exported_symbols_list ${CMAKE_PROJECT_ROOT}/src/msix/exports.def")
|
||||
ELSE()
|
||||
# on Linux and linux-derived platforms, you use a version script to achieve similar ends.
|
||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden")
|
||||
set(DEFINE_EXPORTS "-Wl,--version-script=${CMAKE_PROJECT_ROOT}/src/xPlatAppx/symbol.map")
|
||||
set(DEFINE_EXPORTS "-Wl,--version-script=${CMAKE_PROJECT_ROOT}/src/msix/symbol.map")
|
||||
ENDIF()
|
||||
MESSAGE(STATUS "Using export flag: ${DEFINE_EXPORTS}")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${DEFINE_EXPORTS}")
|
||||
|
@ -80,7 +80,7 @@ file(WRITE "../inc/ContentTypesSchemas.hpp" "${CONTENT_TYPES_HEADER}")
|
|||
|
||||
set(LIB_PUBLIC_HEADERS
|
||||
../inc/AppxPackaging.hpp
|
||||
../inc/AppxWindows.hpp
|
||||
../inc/MSIXWindows.hpp
|
||||
)
|
||||
|
||||
set(LIB_PRIVATE_HEADERS
|
||||
|
@ -115,7 +115,7 @@ set(LIB_SOURCES
|
|||
InflateStream.cpp
|
||||
Log.cpp
|
||||
UnicodeConversion.cpp
|
||||
xPlatAppx.cpp
|
||||
msix.cpp
|
||||
ZipObject.cpp
|
||||
${DirectoryObject}
|
||||
${SHA256}
|
||||
|
@ -123,7 +123,7 @@ set(LIB_SOURCES
|
|||
)
|
||||
|
||||
# Copy out public headers
|
||||
configure_file(../inc/AppxWindows.hpp ${CMAKE_CURRENT_BINARY_DIR}/AppxWindows.hpp )
|
||||
configure_file(../inc/MSIXWindows.hpp ${CMAKE_CURRENT_BINARY_DIR}/MSIXWindows.hpp )
|
||||
configure_file(../inc/AppxPackaging.hpp ${CMAKE_CURRENT_BINARY_DIR}/AppxPackaging.hpp)
|
||||
|
||||
# Define the library
|
||||
|
@ -140,7 +140,7 @@ set_target_properties(${LIBRARY_NAME} PROPERTIES
|
|||
PUBLIC_HEADER "${LIB_HEADERS}" # specify the public headers
|
||||
)
|
||||
|
||||
MESSAGE(STATUS "xPlatAppx takes a static dependency on zlib and xerces")
|
||||
MESSAGE(STATUS "MSIX takes a static dependency on zlib and xerces")
|
||||
include_directories(
|
||||
${include_directories}
|
||||
${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/zlib
|
|
@ -8,7 +8,7 @@
|
|||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
namespace xPlat {
|
||||
namespace MSIX {
|
||||
InflateStream::InflateStream(
|
||||
IStream* stream, std::uint64_t uncompressedSize
|
||||
) : m_stream(stream),
|
||||
|
@ -190,5 +190,5 @@ namespace xPlat {
|
|||
m_state = State::UNINITIALIZED;
|
||||
}
|
||||
}
|
||||
} /* xPlat */
|
||||
} /* msix */
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
#include "Log.hpp"
|
||||
#include <string>
|
||||
|
||||
namespace xPlat { namespace Global { namespace Log {
|
||||
namespace MSIX { namespace Global { namespace Log {
|
||||
|
||||
static std::string g_content;
|
||||
|
||||
|
@ -27,4 +27,4 @@ void Clear()
|
|||
g_content.clear();
|
||||
}
|
||||
|
||||
} /* log */ } /* Global */ } /* xPlat */
|
||||
} /* log */ } /* Global */ } /* msix */
|
|
@ -8,7 +8,7 @@
|
|||
#include <errno.h>
|
||||
#include <fts.h>
|
||||
|
||||
namespace xPlat {
|
||||
namespace MSIX {
|
||||
|
||||
std::vector<std::string> DirectoryObject::GetFileNames(FileNameOptions)
|
||||
{
|
||||
|
@ -47,7 +47,7 @@ namespace xPlat {
|
|||
}
|
||||
}
|
||||
|
||||
IStream* DirectoryObject::OpenFile(const std::string& fileName, xPlat::FileStream::Mode mode)
|
||||
IStream* DirectoryObject::OpenFile(const std::string& fileName, MSIX::FileStream::Mode mode)
|
||||
{
|
||||
std::string name = m_root + "/" + fileName;
|
||||
auto lastSlash = name.find_last_of("/");
|
|
@ -10,10 +10,10 @@
|
|||
#include <sstream>
|
||||
#include <locale>
|
||||
#include <codecvt>
|
||||
#include "AppxWindows.hpp"
|
||||
#include "MSIXWindows.hpp"
|
||||
#include "UnicodeConversion.hpp"
|
||||
|
||||
namespace xPlat {
|
||||
namespace MSIX {
|
||||
enum class WalkOptions : std::uint16_t
|
||||
{
|
||||
Files = 1, // Enumerate files within the specified directory
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include "openssl/sha.h"
|
||||
|
||||
namespace xPlat {
|
||||
namespace MSIX {
|
||||
bool SHA256::ComputeHash(
|
||||
/*in*/ std::uint8_t *buffer,
|
||||
/*in*/ std::uint32_t cbBuffer,
|
||||
|
@ -13,4 +13,4 @@ namespace xPlat {
|
|||
::SHA256(buffer, cbBuffer, hash.data());
|
||||
return true;
|
||||
}
|
||||
} // namespace xPlat {
|
||||
} // namespace MSIX {
|
|
@ -25,7 +25,7 @@ struct unique_alg_handle_deleter {
|
|||
typedef std::unique_ptr<void, unique_alg_handle_deleter> unique_alg_handle;
|
||||
typedef std::unique_ptr<void, unique_hash_handle_deleter> unique_hash_handle;
|
||||
|
||||
namespace xPlat {
|
||||
namespace MSIX {
|
||||
|
||||
bool SHA256::ComputeHash(std::uint8_t* buffer, std::uint32_t cbBuffer, std::vector<uint8_t>& hash)
|
||||
{
|
||||
|
@ -44,7 +44,7 @@ namespace xPlat {
|
|||
0); // Flags; Loads a provider which supports reusable hash
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{ throw xPlat::NtStatusException(status, "failed computing SHA256 hash");
|
||||
{ throw MSIX::NtStatusException(status, "failed computing SHA256 hash");
|
||||
}
|
||||
|
||||
unique_alg_handle algHandle(algHandleT);
|
||||
|
@ -59,7 +59,7 @@ namespace xPlat {
|
|||
0); // Flags
|
||||
|
||||
if (!NT_SUCCESS(status) || resultLength != sizeof(hashLength))
|
||||
{ throw xPlat::NtStatusException(status, "failed computing SHA256 hash");
|
||||
{ throw MSIX::NtStatusException(status, "failed computing SHA256 hash");
|
||||
}
|
||||
|
||||
// Size the hash buffer appropriately
|
||||
|
@ -76,7 +76,7 @@ namespace xPlat {
|
|||
0); // Flags
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{ throw xPlat::NtStatusException(status, "failed computing SHA256 hash");
|
||||
{ throw MSIX::NtStatusException(status, "failed computing SHA256 hash");
|
||||
}
|
||||
|
||||
unique_hash_handle hashHandle(hashHandleT);
|
||||
|
@ -89,7 +89,7 @@ namespace xPlat {
|
|||
0); // Flags
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{ throw xPlat::NtStatusException(status, "failed computing SHA256 hash");
|
||||
{ throw MSIX::NtStatusException(status, "failed computing SHA256 hash");
|
||||
}
|
||||
|
||||
// Obtain the hash of the message(s) into the hash buffer
|
||||
|
@ -100,7 +100,7 @@ namespace xPlat {
|
|||
0); // Flags
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
{ throw xPlat::NtStatusException(status, "failed computing SHA256 hash");
|
||||
{ throw MSIX::NtStatusException(status, "failed computing SHA256 hash");
|
||||
}
|
||||
|
||||
return true;
|
|
@ -17,7 +17,7 @@
|
|||
#include <openssl/pem.h>
|
||||
#include <openssl/crypto.h>
|
||||
|
||||
namespace xPlat
|
||||
namespace MSIX
|
||||
{
|
||||
const char* SPC_INDIRECT_DATA_OBJID = {"1.3.6.1.4.1.311.2.1.4"};
|
||||
|
||||
|
@ -126,10 +126,10 @@ namespace xPlat
|
|||
}
|
||||
|
||||
bool ReadDigestHashes(/*[in]*/ PKCS7* p7,
|
||||
/*[inout]*/ std::map<xPlat::AppxSignatureObject::DigestName, xPlat::AppxSignatureObject::Digest>& digests,
|
||||
/*[inout]*/ std::map<MSIX::AppxSignatureObject::DigestName, MSIX::AppxSignatureObject::Digest>& digests,
|
||||
/*[inout]*/ unique_BIO& signatureDigest)
|
||||
{
|
||||
ThrowErrorIf(Error::AppxSignatureInvalid,
|
||||
ThrowErrorIf(Error::SignatureInvalid,
|
||||
!(p7 &&
|
||||
PKCS7_type_is_signed(p7) &&
|
||||
p7->d.sign &&
|
||||
|
@ -163,7 +163,7 @@ namespace xPlat
|
|||
spcIndirectDataContentSize = (asn1Sequence->rle16.lengthHigh << 8) + (asn1Sequence->rle16.lengthLow);
|
||||
}
|
||||
|
||||
ThrowErrorIf(Error::AppxSignatureInvalid,
|
||||
ThrowErrorIf(Error::SignatureInvalid,
|
||||
(spcIndirectDataContent == nullptr || spcIndirectDataContentSize == 0),
|
||||
"bad signature data");
|
||||
|
||||
|
@ -177,7 +177,7 @@ namespace xPlat
|
|||
bool found = false;
|
||||
while (spcIndirectDataContent < spcIndirectDataContentEnd && !found)
|
||||
{
|
||||
if (*(xPlat::AppxSignatureObject::DigestName *)spcIndirectDataContent == xPlat::AppxSignatureObject::DigestName::HEAD)
|
||||
if (*(MSIX::AppxSignatureObject::DigestName *)spcIndirectDataContent == MSIX::AppxSignatureObject::DigestName::HEAD)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
|
@ -186,16 +186,16 @@ namespace xPlat
|
|||
spcIndirectDataContentSize--;
|
||||
}
|
||||
|
||||
ThrowErrorIf(Error::AppxSignatureInvalid, (!found), "Could not find the digest hashes in the signature");
|
||||
ThrowErrorIf(Error::SignatureInvalid, (!found), "Could not find the digest hashes in the signature");
|
||||
|
||||
// If we found the APPX header, validate the contents
|
||||
DigestHeader *header = reinterpret_cast<DigestHeader*>(spcIndirectDataContent);
|
||||
std::uint32_t numberOfHashes =
|
||||
(spcIndirectDataContentSize - sizeof(xPlat::AppxSignatureObject::DigestName)) / sizeof(DigestHash);
|
||||
(spcIndirectDataContentSize - sizeof(MSIX::AppxSignatureObject::DigestName)) / sizeof(DigestHash);
|
||||
std::uint32_t modHashes =
|
||||
(spcIndirectDataContentSize - sizeof(xPlat::AppxSignatureObject::DigestName)) % sizeof(DigestHash);
|
||||
ThrowErrorIf(Error::AppxSignatureInvalid, (
|
||||
(header->name != xPlat::AppxSignatureObject::DigestName::HEAD) &&
|
||||
(spcIndirectDataContentSize - sizeof(MSIX::AppxSignatureObject::DigestName)) % sizeof(DigestHash);
|
||||
ThrowErrorIf(Error::SignatureInvalid, (
|
||||
(header->name != MSIX::AppxSignatureObject::DigestName::HEAD) &&
|
||||
(numberOfHashes != 4 && numberOfHashes != 5) &&
|
||||
(modHashes != 0)
|
||||
), "bad signature data");
|
||||
|
@ -205,21 +205,21 @@ namespace xPlat
|
|||
std::vector<std::uint8_t> hash(HASH_BYTES);
|
||||
switch (header->hash[i].name)
|
||||
{
|
||||
case xPlat::AppxSignatureObject::DigestName::AXPC:
|
||||
case xPlat::AppxSignatureObject::DigestName::AXCT:
|
||||
case xPlat::AppxSignatureObject::DigestName::AXBM:
|
||||
case xPlat::AppxSignatureObject::DigestName::AXCI:
|
||||
case xPlat::AppxSignatureObject::DigestName::AXCD:
|
||||
case MSIX::AppxSignatureObject::DigestName::AXPC:
|
||||
case MSIX::AppxSignatureObject::DigestName::AXCT:
|
||||
case MSIX::AppxSignatureObject::DigestName::AXBM:
|
||||
case MSIX::AppxSignatureObject::DigestName::AXCI:
|
||||
case MSIX::AppxSignatureObject::DigestName::AXCD:
|
||||
hash.assign(&header->hash[i].content[0], &header->hash[i].content[HASH_BYTES]);
|
||||
digests.emplace(header->hash[i].name, hash);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw xPlat::Exception(xPlat::Error::AppxSignatureInvalid);
|
||||
throw MSIX::Exception(MSIX::Error::SignatureInvalid);
|
||||
}
|
||||
}
|
||||
|
||||
ThrowErrorIf(Error::AppxSignatureInvalid,
|
||||
ThrowErrorIf(Error::SignatureInvalid,
|
||||
(digests.size() != 4 && digests.size() != 5),
|
||||
"Digest hashes missing entries");
|
||||
|
||||
|
@ -324,30 +324,30 @@ namespace xPlat
|
|||
}
|
||||
|
||||
bool SignatureValidator::Validate(
|
||||
/*in*/ APPX_VALIDATION_OPTION option,
|
||||
/*in*/ IStream *stream,
|
||||
/*inout*/ std::map<xPlat::AppxSignatureObject::DigestName, xPlat::AppxSignatureObject::Digest>& digests,
|
||||
/*inout*/ SignatureOrigin& origin,
|
||||
/*inout*/ std::string& publisher)
|
||||
MSIX_VALIDATION_OPTION option,
|
||||
IStream *stream,
|
||||
std::map<MSIX::AppxSignatureObject::DigestName, MSIX::AppxSignatureObject::Digest>& digests,
|
||||
SignatureOrigin& origin,
|
||||
std::string& publisher)
|
||||
{
|
||||
// If the caller wants to skip signature validation altogether, just bug out early. We will not read the digests
|
||||
if (option & APPX_VALIDATION_OPTION_SKIPSIGNATURE) { return false; }
|
||||
if (option & MSIX_VALIDATION_OPTION_SKIPSIGNATURE) { return false; }
|
||||
|
||||
LARGE_INTEGER start = {0};
|
||||
ULARGE_INTEGER end = {0};
|
||||
ThrowHrIfFailed(stream->Seek(start, StreamBase::Reference::END, &end));
|
||||
ThrowErrorIf(Error::AppxSignatureInvalid, (end.QuadPart <= sizeof(P7X_FILE_ID) || end.QuadPart > (2 << 20)), "stream is too big");
|
||||
ThrowErrorIf(Error::SignatureInvalid, (end.QuadPart <= sizeof(P7X_FILE_ID) || end.QuadPart > (2 << 20)), "stream is too big");
|
||||
ThrowHrIfFailed(stream->Seek(start, StreamBase::Reference::START, nullptr));
|
||||
|
||||
std::uint32_t fileID = 0;
|
||||
ThrowHrIfFailed(stream->Read(&fileID, sizeof(fileID), nullptr));
|
||||
ThrowErrorIf(Error::AppxSignatureInvalid, (fileID != P7X_FILE_ID), "unexpected p7x header");
|
||||
ThrowErrorIf(Error::SignatureInvalid, (fileID != P7X_FILE_ID), "unexpected p7x header");
|
||||
|
||||
std::uint32_t p7sSize = end.u.LowPart - sizeof(fileID);
|
||||
std::vector<std::uint8_t> p7s(p7sSize);
|
||||
ULONG actualRead = 0;
|
||||
ThrowHrIfFailed(stream->Read(p7s.data(), p7s.size(), &actualRead));
|
||||
ThrowErrorIf(Error::AppxSignatureInvalid, (actualRead != p7s.size()), "read error");
|
||||
ThrowErrorIf(Error::SignatureInvalid, (actualRead != p7s.size()), "read error");
|
||||
|
||||
// Load the p7s into a BIO buffer
|
||||
unique_BIO bmem(BIO_new_mem_buf(p7s.data(), p7s.size()));
|
||||
|
@ -375,7 +375,7 @@ namespace xPlat
|
|||
unique_X509 cert(PEM_read_bio_X509(bcert.get(), nullptr, nullptr, nullptr));
|
||||
|
||||
// Add the cert to the trusted store
|
||||
ThrowErrorIfNot(Error::AppxSignatureInvalid,
|
||||
ThrowErrorIfNot(Error::SignatureInvalid,
|
||||
X509_STORE_add_cert(store.get(), cert.get()) == 1,
|
||||
"Could not add cert to keychain");
|
||||
|
||||
|
@ -386,7 +386,7 @@ namespace xPlat
|
|||
ReadDigestHashes(p7.get(), digests, signatureDigest);
|
||||
|
||||
// Loop through the untrusted certs and verify them if we're going to treat
|
||||
if (APPX_VALIDATION_OPTION_ALLOWSIGNATUREORIGINUNKNOWN != (option & APPX_VALIDATION_OPTION::APPX_VALIDATION_OPTION_ALLOWSIGNATUREORIGINUNKNOWN))
|
||||
if (MSIX_VALIDATION_OPTION_ALLOWSIGNATUREORIGINUNKNOWN != (option & MSIX_VALIDATION_OPTION::MSIX_VALIDATION_OPTION_ALLOWSIGNATUREORIGINUNKNOWN))
|
||||
{
|
||||
STACK_OF(X509) *untrustedCerts = p7.get()->d.sign->cert;
|
||||
for (int i = 0; i < sk_X509_num(untrustedCerts); i++)
|
||||
|
@ -403,35 +403,35 @@ namespace xPlat
|
|||
X509_VERIFY_PARAM_set_flags(param,
|
||||
X509_V_FLAG_CB_ISSUER_CHECK | X509_V_FLAG_TRUSTED_FIRST | X509_V_FLAG_IGNORE_CRITICAL);
|
||||
|
||||
ThrowErrorIfNot(Error::AppxCertNotTrusted,
|
||||
ThrowErrorIfNot(Error::CertNotTrusted,
|
||||
X509_verify_cert(context.get()) == 1,
|
||||
"Could not verify cert");
|
||||
}
|
||||
|
||||
ThrowErrorIfNot(Error::AppxSignatureInvalid,
|
||||
ThrowErrorIfNot(Error::SignatureInvalid,
|
||||
PKCS7_verify(p7.get(), trustedChain.get(), store.get(), signatureDigest.get(), nullptr/*out*/, PKCS7_NOCRL/*flags*/) == 1,
|
||||
"Could not verify package signature");
|
||||
}
|
||||
|
||||
origin = xPlat::SignatureOrigin::Unknown;
|
||||
if (IsStoreOrigin(p7s.data(), p7s.size())) { origin = xPlat::SignatureOrigin::Store; }
|
||||
else if (IsAuthenticodeOrigin(p7s.data(), p7s.size())) { origin = xPlat::SignatureOrigin::LOB; }
|
||||
origin = MSIX::SignatureOrigin::Unknown;
|
||||
if (IsStoreOrigin(p7s.data(), p7s.size())) { origin = MSIX::SignatureOrigin::Store; }
|
||||
else if (IsAuthenticodeOrigin(p7s.data(), p7s.size())) { origin = MSIX::SignatureOrigin::LOB; }
|
||||
|
||||
bool SignatureOriginUnknownAllowed = (option & APPX_VALIDATION_OPTION_ALLOWSIGNATUREORIGINUNKNOWN) == APPX_VALIDATION_OPTION_ALLOWSIGNATUREORIGINUNKNOWN;
|
||||
ThrowErrorIf(Error::AppxCertNotTrusted,
|
||||
((xPlat::SignatureOrigin::Unknown == origin) && !SignatureOriginUnknownAllowed),
|
||||
bool SignatureOriginUnknownAllowed = (option & MSIX_VALIDATION_OPTION_ALLOWSIGNATUREORIGINUNKNOWN) == MSIX_VALIDATION_OPTION_ALLOWSIGNATUREORIGINUNKNOWN;
|
||||
ThrowErrorIf(Error::CertNotTrusted,
|
||||
((MSIX::SignatureOrigin::Unknown == origin) && !SignatureOriginUnknownAllowed),
|
||||
"Unknown signature origin");
|
||||
|
||||
ThrowErrorIfNot(Error::AppxSignatureInvalid, (
|
||||
xPlat::SignatureOrigin::Store == origin ||
|
||||
xPlat::SignatureOrigin::LOB == origin ||
|
||||
ThrowErrorIfNot(Error::SignatureInvalid, (
|
||||
MSIX::SignatureOrigin::Store == origin ||
|
||||
MSIX::SignatureOrigin::LOB == origin ||
|
||||
SignatureOriginUnknownAllowed
|
||||
), "Signature origin check failed");
|
||||
|
||||
ThrowErrorIfNot(Error::AppxSignatureInvalid, (
|
||||
ThrowErrorIfNot(Error::SignatureInvalid, (
|
||||
GetPublisherName(p7, publisher) == true
|
||||
), "Signature origin check failed");
|
||||
|
||||
return true;
|
||||
}
|
||||
} // namespace xPlat
|
||||
} // namespace MSIX
|
|
@ -9,7 +9,7 @@
|
|||
#include "FileStream.hpp"
|
||||
#include "SignatureValidator.hpp"
|
||||
|
||||
namespace xPlat
|
||||
namespace MSIX
|
||||
{
|
||||
struct unique_local_alloc_deleter {
|
||||
void operator()(HLOCAL h) const { LocalFree(h); };
|
||||
|
@ -76,7 +76,7 @@ namespace xPlat
|
|||
CRYPT_DATA_BLOB signatureBlob = { 0 };
|
||||
signatureBlob.cbData = cbSignatureBuffer;
|
||||
signatureBlob.pbData = signatureBuffer;
|
||||
ThrowErrorIfNot(Error::AppxSignatureInvalid, (
|
||||
ThrowErrorIfNot(Error::SignatureInvalid, (
|
||||
CryptQueryObject(
|
||||
CERT_QUERY_OBJECT_BLOB,
|
||||
&signatureBlob,
|
||||
|
@ -97,18 +97,18 @@ namespace xPlat
|
|||
// The properties of the signer info will be used to uniquely identify the signing certificate in the certificate store
|
||||
CMSG_SIGNER_INFO* signerInfo = NULL;
|
||||
DWORD signerInfoSize = 0;
|
||||
ThrowErrorIfNot(Error::AppxSignatureInvalid, (
|
||||
ThrowErrorIfNot(Error::SignatureInvalid, (
|
||||
CryptMsgGetParam(signedMessage.get(), CMSG_SIGNER_INFO_PARAM, 0, NULL, &signerInfoSize)
|
||||
), "CryptMsgGetParam failed");
|
||||
|
||||
// Check that the signer info size is within reasonable bounds; under the max length of a string for the issuer field
|
||||
ThrowErrorIf(Error::AppxSignatureInvalid,
|
||||
ThrowErrorIf(Error::SignatureInvalid,
|
||||
(signerInfoSize == 0 || signerInfoSize >= STRSAFE_MAX_CCH),
|
||||
"signer info size not within reasonable bounds");
|
||||
|
||||
std::vector<byte> signerInfoBuffer(signerInfoSize);
|
||||
signerInfo = reinterpret_cast<CMSG_SIGNER_INFO*>(signerInfoBuffer.data());
|
||||
ThrowErrorIfNot(Error::AppxSignatureInvalid, (
|
||||
ThrowErrorIfNot(Error::SignatureInvalid, (
|
||||
CryptMsgGetParam(signedMessage.get(), CMSG_SIGNER_INFO_PARAM, 0, signerInfo, &signerInfoSize)
|
||||
), "CryptMsgGetParam failed");
|
||||
|
||||
|
@ -120,7 +120,7 @@ namespace xPlat
|
|||
certStore.get(),
|
||||
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
|
||||
&certInfo));
|
||||
ThrowErrorIf(Error::AppxSignatureInvalid, (signingCertContext.get() == NULL), "failed to get signing cert context.");
|
||||
ThrowErrorIf(Error::SignatureInvalid, (signingCertContext.get() == NULL), "failed to get signing cert context.");
|
||||
|
||||
// Get the signing certificate chain context. Do not connect online for URL
|
||||
// retrievals. Note that this check does not respect the lifetime signing
|
||||
|
@ -130,7 +130,7 @@ namespace xPlat
|
|||
certChainParameters.RequestedUsage.dwType = USAGE_MATCH_TYPE_AND;
|
||||
DWORD certChainFlags = CERT_CHAIN_CACHE_ONLY_URL_RETRIEVAL;
|
||||
PCCERT_CHAIN_CONTEXT certChainContext;
|
||||
ThrowErrorIfNot(Error::AppxSignatureInvalid, (
|
||||
ThrowErrorIfNot(Error::SignatureInvalid, (
|
||||
CertGetCertificateChain(
|
||||
HCCE_LOCAL_MACHINE,
|
||||
signingCertContext.get(),
|
||||
|
@ -153,7 +153,7 @@ namespace xPlat
|
|||
std::vector<byte> extensionUsage(0);
|
||||
CertGetEnhancedKeyUsage(pCertContext, CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &cbExtensionUsage);
|
||||
extensionUsage.resize(cbExtensionUsage);
|
||||
ThrowErrorIf(Error::AppxSignatureInvalid, (
|
||||
ThrowErrorIf(Error::SignatureInvalid, (
|
||||
!CertGetEnhancedKeyUsage(
|
||||
pCertContext,
|
||||
CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG,
|
||||
|
@ -175,7 +175,7 @@ namespace xPlat
|
|||
std::vector<byte> propertyUsage(0);
|
||||
CertGetEnhancedKeyUsage(pCertContext, CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, NULL, &cbPropertyUsage);
|
||||
propertyUsage.resize(cbPropertyUsage);
|
||||
ThrowErrorIf(Error::AppxSignatureInvalid, (
|
||||
ThrowErrorIf(Error::SignatureInvalid, (
|
||||
!CertGetEnhancedKeyUsage(
|
||||
pCertContext,
|
||||
CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG,
|
||||
|
@ -205,7 +205,7 @@ namespace xPlat
|
|||
BYTE keyId[HASH_BYTES];
|
||||
DWORD keyIdLength = HASH_BYTES;
|
||||
|
||||
ThrowErrorIfNot(Error::AppxSignatureInvalid,
|
||||
ThrowErrorIfNot(Error::SignatureInvalid,
|
||||
(CryptHashCertificate2(
|
||||
BCRYPT_SHA256_ALGORITHM,
|
||||
0, // dwFlags
|
||||
|
@ -227,7 +227,7 @@ namespace xPlat
|
|||
policyStatus.cbSize = sizeof(CERT_CHAIN_POLICY_STATUS);
|
||||
policyParameters.dwFlags = MICROSOFT_ROOT_CERT_CHAIN_POLICY_CHECK_APPLICATION_ROOT_FLAG;
|
||||
|
||||
ThrowErrorIfNot(Error::AppxSignatureInvalid,
|
||||
ThrowErrorIfNot(Error::SignatureInvalid,
|
||||
CertVerifyCertificateChainPolicy(
|
||||
CERT_CHAIN_POLICY_MICROSOFT_ROOT,
|
||||
certChainContext,
|
||||
|
@ -251,7 +251,7 @@ namespace xPlat
|
|||
policyStatus.cbSize = sizeof(CERT_CHAIN_POLICY_STATUS);
|
||||
|
||||
//policyParameters.dwFlags = MICROSOFT_ROOT_CERT_CHAIN_POLICY_CHECK_APPLICATION_ROOT_FLAG;
|
||||
ThrowErrorIfNot(Error::AppxSignatureInvalid,
|
||||
ThrowErrorIfNot(Error::SignatureInvalid,
|
||||
CertVerifyCertificateChainPolicy(
|
||||
CERT_CHAIN_POLICY_AUTHENTICODE,
|
||||
certChainContext,
|
||||
|
@ -265,7 +265,7 @@ namespace xPlat
|
|||
policyParameters.cbSize = sizeof(CERT_CHAIN_POLICY_PARA);
|
||||
policyStatus = {0};
|
||||
policyStatus.cbSize = sizeof(CERT_CHAIN_POLICY_STATUS);
|
||||
ThrowErrorIfNot(Error::AppxSignatureInvalid,
|
||||
ThrowErrorIfNot(Error::SignatureInvalid,
|
||||
CertVerifyCertificateChainPolicy(
|
||||
CERT_CHAIN_POLICY_BASE,
|
||||
certChainContext,
|
||||
|
@ -331,7 +331,7 @@ namespace xPlat
|
|||
CERT_BLOB blob;
|
||||
blob.pbData = signatureBuffer;
|
||||
blob.cbData = cbSignatureBuffer;
|
||||
ThrowErrorIfNot(Error::AppxSignatureInvalid, (
|
||||
ThrowErrorIfNot(Error::SignatureInvalid, (
|
||||
CryptQueryObject(
|
||||
CERT_QUERY_OBJECT_BLOB,
|
||||
&blob,
|
||||
|
@ -427,28 +427,28 @@ namespace xPlat
|
|||
|
||||
|
||||
bool SignatureValidator::Validate(
|
||||
/*in*/ APPX_VALIDATION_OPTION option,
|
||||
/*in*/ IStream *stream,
|
||||
/*inout*/ std::map<xPlat::AppxSignatureObject::DigestName, xPlat::AppxSignatureObject::Digest>& digests,
|
||||
/*inout*/ SignatureOrigin& origin,
|
||||
/*inout*/ std::string& publisher)
|
||||
MSIX_VALIDATION_OPTION option,
|
||||
IStream *stream,
|
||||
std::map<MSIX::AppxSignatureObject::DigestName, MSIX::AppxSignatureObject::Digest>& digests,
|
||||
SignatureOrigin& origin,
|
||||
std::string& publisher)
|
||||
{
|
||||
// If the caller wants to skip signature validation altogether, just bug out early. We will not read the digests
|
||||
if (option & APPX_VALIDATION_OPTION_SKIPSIGNATURE) { return false; }
|
||||
if (option & MSIX_VALIDATION_OPTION_SKIPSIGNATURE) { return false; }
|
||||
|
||||
ThrowErrorIfNot(Error::AppxMissingSignatureP7X, (stream), "AppxSignature.p7x missing");
|
||||
ThrowErrorIfNot(Error::MissingAppxSignatureP7X, (stream), "AppxSignature.p7x missing");
|
||||
|
||||
LARGE_INTEGER li = {0};
|
||||
ULARGE_INTEGER uli = {0};
|
||||
ThrowHrIfFailed(stream->Seek(li, StreamBase::Reference::END, &uli));
|
||||
ThrowErrorIf(Error::AppxSignatureInvalid, (uli.QuadPart <= sizeof(P7X_FILE_ID) || uli.QuadPart > (2 << 20)), "stream is too big");
|
||||
ThrowErrorIf(Error::SignatureInvalid, (uli.QuadPart <= sizeof(P7X_FILE_ID) || uli.QuadPart > (2 << 20)), "stream is too big");
|
||||
|
||||
std::vector<std::uint8_t> p7x(uli.LowPart);
|
||||
ThrowHrIfFailed(stream->Seek(li, StreamBase::Reference::START, &uli));
|
||||
|
||||
ULONG actualRead = 0;
|
||||
ThrowHrIfFailed(stream->Read(p7x.data(), p7x.size(), &actualRead));
|
||||
ThrowErrorIf(Error::AppxSignatureInvalid,
|
||||
ThrowErrorIf(Error::SignatureInvalid,
|
||||
((actualRead != p7x.size() || (*(DWORD*)p7x.data() != P7X_FILE_ID))),
|
||||
"Failed to read p7x or p7x header mismatch");
|
||||
|
||||
|
@ -458,7 +458,7 @@ namespace xPlat
|
|||
// Decode the ASN.1 structure
|
||||
CRYPT_CONTENT_INFO* contentInfo = nullptr;
|
||||
DWORD contentInfoSize = 0;
|
||||
ThrowErrorIfNot(Error::AppxSignatureInvalid, (
|
||||
ThrowErrorIfNot(Error::SignatureInvalid, (
|
||||
CryptDecodeObjectEx(
|
||||
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
|
||||
PKCS_CONTENT_INFO,
|
||||
|
@ -477,11 +477,11 @@ namespace xPlat
|
|||
NULL,
|
||||
nullptr,
|
||||
nullptr);
|
||||
ThrowErrorIf(Error::AppxSignatureInvalid, (cryptMsgT == nullptr), "CryptMsgOpenToDecode failed");
|
||||
ThrowErrorIf(Error::SignatureInvalid, (cryptMsgT == nullptr), "CryptMsgOpenToDecode failed");
|
||||
unique_crypt_msg_handle cryptMsg(cryptMsgT);
|
||||
|
||||
// Get the crypographic message
|
||||
ThrowErrorIfNot(Error::AppxSignatureInvalid, (
|
||||
ThrowErrorIfNot(Error::SignatureInvalid, (
|
||||
CryptMsgUpdate(
|
||||
cryptMsg.get(),
|
||||
contentInfo->Content.pbData,
|
||||
|
@ -493,7 +493,7 @@ namespace xPlat
|
|||
// how big of a buffer that it needs to store the inner content
|
||||
DWORD innerContentTypeSize = 0;
|
||||
ULONG readBytes = 0;
|
||||
ThrowErrorIf(Error::AppxSignatureInvalid, (
|
||||
ThrowErrorIf(Error::SignatureInvalid, (
|
||||
!CryptMsgGetParam(
|
||||
cryptMsg.get(),
|
||||
CMSG_INNER_CONTENT_TYPE_PARAM,
|
||||
|
@ -505,7 +505,7 @@ namespace xPlat
|
|||
|
||||
// Allocate a temporary buffer
|
||||
std::vector<std::uint8_t> innerContentType(innerContentTypeSize);
|
||||
ThrowErrorIfNot(Error::AppxSignatureInvalid, (
|
||||
ThrowErrorIfNot(Error::SignatureInvalid, (
|
||||
CryptMsgGetParam(
|
||||
cryptMsg.get(),
|
||||
CMSG_INNER_CONTENT_TYPE_PARAM,
|
||||
|
@ -515,13 +515,13 @@ namespace xPlat
|
|||
),"CryptMsgGetParam failed");
|
||||
|
||||
size_t indirectDataObjIdLength = strlen(SPC_INDIRECT_DATA_OBJID);
|
||||
ThrowErrorIf(Error::AppxSignatureInvalid, (
|
||||
ThrowErrorIf(Error::SignatureInvalid, (
|
||||
(innerContentTypeSize != indirectDataObjIdLength + 1) ||
|
||||
(strncmp((char*)innerContentType.data(), SPC_INDIRECT_DATA_OBJID, indirectDataObjIdLength + 1) != 0)
|
||||
), "unexpected content type");
|
||||
|
||||
DWORD innerContentSize = 0;
|
||||
ThrowErrorIfNot(Error::AppxSignatureInvalid, (
|
||||
ThrowErrorIfNot(Error::SignatureInvalid, (
|
||||
CryptMsgGetParam(
|
||||
cryptMsg.get(),
|
||||
CMSG_CONTENT_PARAM,
|
||||
|
@ -533,7 +533,7 @@ namespace xPlat
|
|||
|
||||
// Allocate a temporary buffer
|
||||
std::vector<std::uint8_t> innerContent(innerContentSize);
|
||||
ThrowErrorIfNot(Error::AppxSignatureInvalid, (
|
||||
ThrowErrorIfNot(Error::SignatureInvalid, (
|
||||
CryptMsgGetParam(
|
||||
cryptMsg.get(),
|
||||
CMSG_CONTENT_PARAM,
|
||||
|
@ -545,7 +545,7 @@ namespace xPlat
|
|||
// Parse the ASN.1 to the the indirect data structure
|
||||
SPC_INDIRECT_DATA_CONTENT* indirectContent = NULL;
|
||||
DWORD indirectContentSize = 0;
|
||||
ThrowErrorIfNot(Error::AppxSignatureInvalid, (
|
||||
ThrowErrorIfNot(Error::SignatureInvalid, (
|
||||
CryptDecodeObjectEx(
|
||||
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
|
||||
SPC_INDIRECT_DATA_CONTENT_STRUCT,
|
||||
|
@ -560,8 +560,8 @@ namespace xPlat
|
|||
DigestHeader *header = reinterpret_cast<DigestHeader*>(indirectContent->Digest.pbData);
|
||||
std::uint32_t numberOfHashes = (indirectContent->Digest.cbData - sizeof(DWORD)) / sizeof(DigestHash);
|
||||
std::uint32_t modHashes = (indirectContent->Digest.cbData - sizeof(DWORD)) % sizeof(DigestHash);
|
||||
ThrowErrorIf(Error::AppxSignatureInvalid, (
|
||||
(header->name != xPlat::AppxSignatureObject::DigestName::HEAD) &&
|
||||
ThrowErrorIf(Error::SignatureInvalid, (
|
||||
(header->name != MSIX::AppxSignatureObject::DigestName::HEAD) &&
|
||||
(numberOfHashes != 4 && numberOfHashes != 5) &&
|
||||
(modHashes != 0)
|
||||
), "bad signature data");
|
||||
|
@ -571,33 +571,33 @@ namespace xPlat
|
|||
std::vector<std::uint8_t> hash(HASH_BYTES);
|
||||
switch (header->hash[i].name)
|
||||
{
|
||||
case xPlat::AppxSignatureObject::DigestName::AXPC:
|
||||
case xPlat::AppxSignatureObject::DigestName::AXCT:
|
||||
case xPlat::AppxSignatureObject::DigestName::AXBM:
|
||||
case xPlat::AppxSignatureObject::DigestName::AXCI:
|
||||
case xPlat::AppxSignatureObject::DigestName::AXCD:
|
||||
case MSIX::AppxSignatureObject::DigestName::AXPC:
|
||||
case MSIX::AppxSignatureObject::DigestName::AXCT:
|
||||
case MSIX::AppxSignatureObject::DigestName::AXBM:
|
||||
case MSIX::AppxSignatureObject::DigestName::AXCI:
|
||||
case MSIX::AppxSignatureObject::DigestName::AXCD:
|
||||
hash.assign(&header->hash[i].content[0], &header->hash[i].content[HASH_BYTES]);
|
||||
digests.emplace(header->hash[i].name, hash);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw xPlat::Exception(xPlat::Error::AppxSignatureInvalid);
|
||||
throw MSIX::Exception(MSIX::Error::SignatureInvalid);
|
||||
}
|
||||
}
|
||||
|
||||
origin = xPlat::SignatureOrigin::Unknown;
|
||||
if (IsStoreOrigin(p7s, p7sSize)) { origin = xPlat::SignatureOrigin::Store; }
|
||||
else if (IsAuthenticodeOrigin(p7s, p7sSize)) { origin = xPlat::SignatureOrigin::LOB; }
|
||||
origin = MSIX::SignatureOrigin::Unknown;
|
||||
if (IsStoreOrigin(p7s, p7sSize)) { origin = MSIX::SignatureOrigin::Store; }
|
||||
else if (IsAuthenticodeOrigin(p7s, p7sSize)) { origin = MSIX::SignatureOrigin::LOB; }
|
||||
|
||||
bool SignatureOriginUnknownAllowed = (option & APPX_VALIDATION_OPTION_ALLOWSIGNATUREORIGINUNKNOWN) == APPX_VALIDATION_OPTION_ALLOWSIGNATUREORIGINUNKNOWN;
|
||||
ThrowErrorIf(Error::AppxCertNotTrusted,
|
||||
((xPlat::SignatureOrigin::Unknown == origin) && !SignatureOriginUnknownAllowed),
|
||||
bool SignatureOriginUnknownAllowed = (option & MSIX_VALIDATION_OPTION_ALLOWSIGNATUREORIGINUNKNOWN) == MSIX_VALIDATION_OPTION_ALLOWSIGNATUREORIGINUNKNOWN;
|
||||
ThrowErrorIf(Error::CertNotTrusted,
|
||||
((MSIX::SignatureOrigin::Unknown == origin) && !SignatureOriginUnknownAllowed),
|
||||
"Unknown signature origin");
|
||||
|
||||
ThrowErrorIfNot(Error::AppxSignatureInvalid,
|
||||
ThrowErrorIfNot(Error::SignatureInvalid,
|
||||
GetPublisherName(p7s, p7sSize, publisher) == true,
|
||||
"Could not retrieve publisher name");
|
||||
|
||||
return true;
|
||||
}
|
||||
} // namespace xPlat
|
||||
} // namespace MSIX
|
|
@ -5,7 +5,7 @@
|
|||
#include <codecvt>
|
||||
#include "UnicodeConversion.hpp"
|
||||
|
||||
namespace xPlat {
|
||||
namespace MSIX {
|
||||
std::wstring utf8_to_utf16(const std::string& utf8string)
|
||||
{
|
||||
/*
|
||||
|
@ -34,4 +34,4 @@ namespace xPlat {
|
|||
std::string result(converted.begin(), converted.end());
|
||||
return result;
|
||||
}
|
||||
} // namespace xPlat
|
||||
} // namespace MSIX
|
|
@ -12,7 +12,7 @@
|
|||
#include <functional>
|
||||
#include <algorithm>
|
||||
|
||||
namespace xPlat {
|
||||
namespace MSIX {
|
||||
|
||||
/* Zip File Structure
|
||||
[LocalFileHeader 1]
|
||||
|
@ -892,7 +892,7 @@ namespace xPlat {
|
|||
throw Exception(Error::NotImplemented);
|
||||
}
|
||||
|
||||
IStream* ZipObject::OpenFile(const std::string& fileName, xPlat::FileStream::Mode mode)
|
||||
IStream* ZipObject::OpenFile(const std::string& fileName, MSIX::FileStream::Mode mode)
|
||||
{
|
||||
throw Exception(Error::NotImplemented);
|
||||
}
|
||||
|
@ -904,7 +904,7 @@ namespace xPlat {
|
|||
|
||||
std::string ZipObject::GetPathSeparator() { return "/"; }
|
||||
|
||||
ZipObject::ZipObject(IxPlatFactory* appxFactory, IStream* stream) : m_factory(appxFactory), m_stream(stream)
|
||||
ZipObject::ZipObject(IMSIXFactory* appxFactory, IStream* stream) : m_factory(appxFactory), m_stream(stream)
|
||||
{
|
||||
// Confirm that the file IS the correct format
|
||||
EndCentralDirectoryRecord endCentralDirectoryRecord;
|
||||
|
@ -962,7 +962,7 @@ namespace xPlat {
|
|||
for (const auto& centralFileHeader : centralDirectory)
|
||||
{
|
||||
pos.QuadPart = centralFileHeader.second->GetRelativeOffsetOfLocalHeader();
|
||||
ThrowHrIfFailed(m_stream->Seek(pos, xPlat::StreamBase::Reference::START, nullptr));
|
||||
ThrowHrIfFailed(m_stream->Seek(pos, MSIX::StreamBase::Reference::START, nullptr));
|
||||
auto localFileHeader = std::make_shared<LocalFileHeader>(centralFileHeader.second);
|
||||
localFileHeader->Read(m_stream.Get());
|
||||
fileRepository.insert(std::make_pair(
|
||||
|
@ -987,4 +987,4 @@ namespace xPlat {
|
|||
m_streams.insert(std::make_pair(centralFileHeader.second->GetFileName(), std::move(fileStream)));
|
||||
}
|
||||
} // ZipObject::ZipObject
|
||||
} // namespace xPlat
|
||||
} // namespace MSIX
|
|
@ -1,6 +1,6 @@
|
|||
# exports.def
|
||||
# written 1/16/2018 by Phil Smith (psmith@microsoft.com)
|
||||
# This file defines the list of c-style exports for xPlatAppx shared library
|
||||
# This file defines the list of c-style exports for msix shared library
|
||||
# do not remove, reorder, or overload, these exported functions as doing so
|
||||
# will break the ABI contract with clients.
|
||||
# ---------------------------------------------------------------------------
|
||||
|
@ -9,4 +9,5 @@ _CoCreateAppxFactoryWithHeap
|
|||
_CreateStreamOnFile
|
||||
_CreateStreamOnFileUTF16
|
||||
_GetLogTextUTF8
|
||||
_UnpackAppx
|
||||
_UnpackPackage
|
||||
|
|
@ -113,8 +113,8 @@ struct _BLOBHEADER
|
|||
#include <poppack.h>
|
||||
#else
|
||||
// on non-win32 platforms, compile with -fvisibility=hidden
|
||||
#undef XPLATAPPX_API
|
||||
#define XPLATAPPX_API __attribute__((visibility("default")))
|
||||
#undef MSIX_API
|
||||
#define MSIX_API __attribute__((visibility("default")))
|
||||
|
||||
// Initializer.
|
||||
__attribute__((constructor))
|
||||
|
@ -134,90 +134,90 @@ LPVOID STDMETHODCALLTYPE InternalAllocate(SIZE_T cb) { return std::malloc(cb);
|
|||
void STDMETHODCALLTYPE InternalFree(LPVOID pv) { std::free(pv); }
|
||||
|
||||
|
||||
XPLATAPPX_API HRESULT STDMETHODCALLTYPE UnpackAppx(
|
||||
APPX_PACKUNPACK_OPTION packUnpackOptions,
|
||||
APPX_VALIDATION_OPTION validationOption,
|
||||
MSIX_API HRESULT STDMETHODCALLTYPE UnpackPackage(
|
||||
MSIX_PACKUNPACK_OPTION packUnpackOptions,
|
||||
MSIX_VALIDATION_OPTION validationOption,
|
||||
char* utf8SourcePackage,
|
||||
char* utf8Destination)
|
||||
{
|
||||
return xPlat::ResultOf([&]() {
|
||||
ThrowErrorIfNot(xPlat::Error::InvalidParameter,
|
||||
return MSIX::ResultOf([&]() {
|
||||
ThrowErrorIfNot(MSIX::Error::InvalidParameter,
|
||||
(utf8SourcePackage != nullptr && utf8Destination != nullptr),
|
||||
"Invalid parameters"
|
||||
);
|
||||
|
||||
xPlat::ComPtr<IAppxFactory> factory;
|
||||
MSIX::ComPtr<IAppxFactory> factory;
|
||||
// We don't need to use the caller's heap here because we're not marshalling any strings
|
||||
// out to the caller. So default to new / delete[] and be done with it!
|
||||
ThrowHrIfFailed(CoCreateAppxFactoryWithHeap(InternalAllocate, InternalFree, validationOption, &factory));
|
||||
|
||||
xPlat::ComPtr<IStream> stream;
|
||||
MSIX::ComPtr<IStream> stream;
|
||||
ThrowHrIfFailed(CreateStreamOnFile(utf8SourcePackage, true, &stream));
|
||||
|
||||
xPlat::ComPtr<IAppxPackageReader> reader;
|
||||
MSIX::ComPtr<IAppxPackageReader> reader;
|
||||
ThrowHrIfFailed(factory->CreatePackageReader(stream.Get(), &reader));
|
||||
|
||||
auto to = xPlat::ComPtr<IStorageObject>::Make<xPlat::DirectoryObject>(utf8Destination);
|
||||
reader.As<IAppxPackage>()->Unpack(packUnpackOptions, to.Get());
|
||||
auto to = MSIX::ComPtr<IStorageObject>::Make<MSIX::DirectoryObject>(utf8Destination);
|
||||
reader.As<IPackage>()->Unpack(packUnpackOptions, to.Get());
|
||||
});
|
||||
}
|
||||
|
||||
XPLATAPPX_API HRESULT STDMETHODCALLTYPE GetLogTextUTF8(COTASKMEMALLOC* memalloc, char** logText)
|
||||
MSIX_API HRESULT STDMETHODCALLTYPE GetLogTextUTF8(COTASKMEMALLOC* memalloc, char** logText)
|
||||
{
|
||||
return xPlat::ResultOf([&](){
|
||||
ThrowErrorIf(xPlat::Error::InvalidParameter, (logText == nullptr || *logText != nullptr), "bad pointer" );
|
||||
std::size_t countBytes = sizeof(char)*(xPlat::Global::Log::Text().size()+1);
|
||||
return MSIX::ResultOf([&](){
|
||||
ThrowErrorIf(MSIX::Error::InvalidParameter, (logText == nullptr || *logText != nullptr), "bad pointer" );
|
||||
std::size_t countBytes = sizeof(char)*(MSIX::Global::Log::Text().size()+1);
|
||||
*logText = reinterpret_cast<char*>(memalloc(countBytes));
|
||||
ThrowErrorIfNot(xPlat::Error::OutOfMemory, (*logText), "Allocation failed!");
|
||||
ThrowErrorIfNot(MSIX::Error::OutOfMemory, (*logText), "Allocation failed!");
|
||||
std::memset(reinterpret_cast<void*>(*logText), 0, countBytes);
|
||||
std::memcpy(reinterpret_cast<void*>(*logText),
|
||||
reinterpret_cast<void*>(const_cast<char*>(xPlat::Global::Log::Text().c_str())),
|
||||
reinterpret_cast<void*>(const_cast<char*>(MSIX::Global::Log::Text().c_str())),
|
||||
countBytes - sizeof(char));
|
||||
xPlat::Global::Log::Clear();
|
||||
MSIX::Global::Log::Clear();
|
||||
});
|
||||
}
|
||||
|
||||
XPLATAPPX_API HRESULT STDMETHODCALLTYPE CreateStreamOnFile(
|
||||
MSIX_API HRESULT STDMETHODCALLTYPE CreateStreamOnFile(
|
||||
char* utf8File,
|
||||
bool forRead,
|
||||
IStream** stream)
|
||||
{
|
||||
return xPlat::ResultOf([&]() {
|
||||
xPlat::FileStream::Mode mode = forRead ? xPlat::FileStream::Mode::READ : xPlat::FileStream::Mode::WRITE_UPDATE;
|
||||
*stream = xPlat::ComPtr<IStream>::Make<xPlat::FileStream>(utf8File, mode).Detach();
|
||||
return MSIX::ResultOf([&]() {
|
||||
MSIX::FileStream::Mode mode = forRead ? MSIX::FileStream::Mode::READ : MSIX::FileStream::Mode::WRITE_UPDATE;
|
||||
*stream = MSIX::ComPtr<IStream>::Make<MSIX::FileStream>(utf8File, mode).Detach();
|
||||
});
|
||||
}
|
||||
|
||||
XPLATAPPX_API HRESULT STDMETHODCALLTYPE CreateStreamOnFileUTF16(
|
||||
MSIX_API HRESULT STDMETHODCALLTYPE CreateStreamOnFileUTF16(
|
||||
LPCWSTR utf16File,
|
||||
bool forRead,
|
||||
IStream** stream)
|
||||
{
|
||||
return xPlat::ResultOf([&]() {
|
||||
xPlat::FileStream::Mode mode = forRead ? xPlat::FileStream::Mode::READ : xPlat::FileStream::Mode::WRITE_UPDATE;
|
||||
*stream = xPlat::ComPtr<IStream>::Make<xPlat::FileStream>(xPlat::utf16_to_utf8(utf16File), mode).Detach();
|
||||
return MSIX::ResultOf([&]() {
|
||||
MSIX::FileStream::Mode mode = forRead ? MSIX::FileStream::Mode::READ : MSIX::FileStream::Mode::WRITE_UPDATE;
|
||||
*stream = MSIX::ComPtr<IStream>::Make<MSIX::FileStream>(MSIX::utf16_to_utf8(utf16File), mode).Detach();
|
||||
});
|
||||
}
|
||||
|
||||
XPLATAPPX_API HRESULT STDMETHODCALLTYPE CoCreateAppxFactoryWithHeap(
|
||||
MSIX_API HRESULT STDMETHODCALLTYPE CoCreateAppxFactoryWithHeap(
|
||||
COTASKMEMALLOC* memalloc,
|
||||
COTASKMEMFREE* memfree,
|
||||
APPX_VALIDATION_OPTION validationOption,
|
||||
MSIX_VALIDATION_OPTION validationOption,
|
||||
IAppxFactory** appxFactory)
|
||||
{
|
||||
return xPlat::ResultOf([&]() {
|
||||
*appxFactory = xPlat::ComPtr<IAppxFactory>::Make<xPlat::AppxFactory>(validationOption, memalloc, memfree).Detach();
|
||||
return MSIX::ResultOf([&]() {
|
||||
*appxFactory = MSIX::ComPtr<IAppxFactory>::Make<MSIX::AppxFactory>(validationOption, memalloc, memfree).Detach();
|
||||
});
|
||||
}
|
||||
|
||||
// Call specific for Windows. Default to call CoTaskMemAlloc and CoTaskMemFree
|
||||
XPLATAPPX_API HRESULT STDMETHODCALLTYPE CoCreateAppxFactory(
|
||||
APPX_VALIDATION_OPTION validationOption,
|
||||
MSIX_API HRESULT STDMETHODCALLTYPE CoCreateAppxFactory(
|
||||
MSIX_VALIDATION_OPTION validationOption,
|
||||
IAppxFactory** appxFactory)
|
||||
{
|
||||
#ifdef WIN32
|
||||
return CoCreateAppxFactoryWithHeap(CoTaskMemAlloc, CoTaskMemFree, validationOption, appxFactory);
|
||||
#else
|
||||
return static_cast<HRESULT>(xPlat::Error::NotSupported);
|
||||
return static_cast<HRESULT>(MSIX::Error::NotSupported);
|
||||
#endif
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
CreateStreamOnFile;
|
||||
CreateStreamOnFileUTF16;
|
||||
GetLogTextUTF8;
|
||||
UnpackAppx;
|
||||
UnpackPackage;
|
||||
local:
|
||||
*;
|
||||
};
|
|
@ -1,53 +0,0 @@
|
|||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "(lldb) Launch MakeXPlat",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "/Users/admin/code/xPlatAppx/build/bin/MakeXPlat",
|
||||
"args": ["unpack",
|
||||
"-d" ,"/Users/admin/code/xPlatAppx/test/unpack",
|
||||
"-p", "/Users/admin/code/xPlatAppx/test/appx/StoreSigned_Desktop_x64_MoviesTV.appx",
|
||||
"-sv"
|
||||
],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "/Users/admin/code/xPlatAppx/build/bin",
|
||||
"environment": [],
|
||||
"externalConsole": true,
|
||||
"MIMode": "lldb"
|
||||
},
|
||||
{
|
||||
"name": "(lldb) Launch ExtractContentsSample",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceRoot}/build/bin/ExtractContentsSample",
|
||||
"args": [
|
||||
"${workspaceRoot}/test/appx/StoreSigned_Desktop_x64_MoviesTV.appx",
|
||||
"${workspaceRoot}/test/unpack" ],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "${workspaceRoot}/build/bin",
|
||||
"environment": [],
|
||||
"externalConsole": true,
|
||||
"MIMode": "lldb"
|
||||
},
|
||||
{
|
||||
"name": "(Windows) Launch",
|
||||
"type": "cppvsdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceRoot}\\.vs\\bin\\MakeXPlat",
|
||||
"symbolSearchPath" : "${workspaceRoot}\\.vs\\bin",
|
||||
"logging": {
|
||||
"moduleLoad": false,
|
||||
"trace": true
|
||||
},
|
||||
"args": ["unpack",
|
||||
"-d" ,"${workspaceRoot}\\test\\unpack",
|
||||
"-p", "${workspaceRoot}\\test\\appx\\UnsignedZip64WithCI-APPX_E_MISSING_REQUIRED_FILE.appx" ],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "${workspaceRoot}",
|
||||
"environment": [],
|
||||
"externalConsole": true
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
# xplat\test
|
||||
# MSIX\test
|
||||
# Copyright (C) 2017 Microsoft
|
||||
# Created by Phil Smith (psmith@microsoft.com) on 01/29/2018
|
||||
cmake_minimum_required(VERSION 3.4.0 FATAL_ERROR)
|
||||
|
|
|
@ -3,13 +3,13 @@ TESTFAILED=0
|
|||
function FindBinFolder {
|
||||
echo "Searching under" $PWD
|
||||
#look in .vs/bin first
|
||||
if [ -e "../../.vs/bin/MakeXplat" ]
|
||||
if [ -e "../../.vs/bin/makemsix" ]
|
||||
then
|
||||
BINDIR="../../.vs/bin"
|
||||
elif [ -e "../../.vscode/bin/MakeXplat" ]
|
||||
elif [ -e "../../.vscode/bin/makemsix" ]
|
||||
then
|
||||
BINDIR="../../.vscode/bin"
|
||||
elif [ -e "../../build/bin/MakeXplat" ]
|
||||
elif [ -e "../../build/bin/makemsix" ]
|
||||
then
|
||||
BINDIR="../../build/bin"
|
||||
else
|
||||
|
@ -33,9 +33,9 @@ function RunTest {
|
|||
local UNPACKFOLDER="$2"
|
||||
local ARGS="$3"
|
||||
echo "------------------------------------------------------"
|
||||
echo $BINDIR/MakeXplat unpack -d ./../unpack -p $UNPACKFOLDER $ARGS
|
||||
echo $BINDIR/makemsix unpack -d ./../unpack -p $UNPACKFOLDER $ARGS
|
||||
echo "------------------------------------------------------"
|
||||
$BINDIR/MakeXplat unpack -d ./../unpack -p $UNPACKFOLDER $ARGS
|
||||
$BINDIR/makemsix unpack -d ./../unpack -p $UNPACKFOLDER $ARGS
|
||||
local RESULT=$?
|
||||
echo "expect: "$SUCCESS", got: "$RESULT
|
||||
if [ $RESULT -eq $SUCCESS ]
|
||||
|
@ -50,7 +50,7 @@ function RunTest {
|
|||
FindBinFolder
|
||||
# return code is last two digits, but in decimal, not hex. e.g. 0x8bad0002 == 2, 0x8bad0041 == 65, etc...
|
||||
# common codes:
|
||||
# AppxSignatureInvalid = ERROR_FACILITY + 0x0041 == 65
|
||||
# SignatureInvalid = ERROR_FACILITY + 0x0041 == 65
|
||||
|
||||
RunTest 2 ./../appx/Empty.appx -sv
|
||||
RunTest 0 ./../appx/HelloWorld.appx -ss
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/bin/bash
|
||||
testfailed=0
|
||||
xplatappxdir=`pwd`
|
||||
projectdir=`pwd`
|
||||
|
||||
function RunCommandWithTimeout {
|
||||
local result=1
|
||||
|
@ -43,25 +43,25 @@ function StartEmulator {
|
|||
|
||||
function CreateApp {
|
||||
# Prepare package and compile
|
||||
cd $xplatappxdir/../mobile/xPlatAppxAndroid
|
||||
cd $projectdir/../mobile/AndroidBVT
|
||||
mkdir app/src/main/assets
|
||||
cp -R $xplatappxdir/../appx/* app/src/main/assets
|
||||
cp -R $projectdir/../appx/* app/src/main/assets
|
||||
mkdir -p app/src/main/jniLibs/x86
|
||||
cp $xplatappxdir/../../.vs/lib/libxPlatAppx.so app/src/main/jniLibs/x86
|
||||
cp $projectdir/../../.vs/lib/libmsix.so app/src/main/jniLibs/x86
|
||||
rm -r build app/build
|
||||
sh ./gradlew assembleDebug
|
||||
}
|
||||
|
||||
function RunTest {
|
||||
# Install app
|
||||
RunCommand "adb push app/build/outputs/apk/debug/app-debug.apk /data/local/tmp/com.microsoft.xplatappxandroid"
|
||||
RunCommand "adb shell pm install -t -r '/data/local/tmp/com.microsoft.xplatappxandroid'"
|
||||
RunCommand "adb push app/build/outputs/apk/debug/app-debug.apk /data/local/tmp/com.microsoft.androidbvt"
|
||||
RunCommand "adb shell pm install -t -r '/data/local/tmp/com.microsoft.androidbvt'"
|
||||
# Start app
|
||||
RunCommand "adb shell am start -n 'com.microsoft.xplatappxandroid/com.microsoft.xplatappxandroid.MainActivity' -a android.intent.action.MAIN -c android.intent.category.LAUNCHER"
|
||||
RunCommand "adb shell am start -n 'com.microsoft.androidbvt/com.microsoft.androidbvt.MainActivity' -a android.intent.action.MAIN -c android.intent.category.LAUNCHER"
|
||||
# The apps terminates when is done
|
||||
sleep 30
|
||||
# Get Results
|
||||
RunCommand "adb pull /data/data/com.microsoft.xplatappxandroid/files/testResults.txt"
|
||||
RunCommand "adb pull /data/data/com.microsoft.androidbvt/files/testResults.txt"
|
||||
}
|
||||
|
||||
function ParseResult {
|
||||
|
@ -85,8 +85,8 @@ function ParseResult {
|
|||
|
||||
StartEmulator
|
||||
# Clean up. This commands might fail, but is not an error
|
||||
adb shell rm -r /data/data/com.microsoft.xplatappxandroid/files
|
||||
rm $xplatappxdir/../mobile/xPlatAppxAndroid/testResults.txt
|
||||
adb shell rm -r /data/data/com.microsoft.androidbvt/files
|
||||
rm $projectdir/../mobile/androidbvt/testResults.txt
|
||||
|
||||
CreateApp
|
||||
RunTest
|
||||
|
|
|
@ -4,15 +4,15 @@ $global:BINDIR=""
|
|||
|
||||
function FindBinFolder {
|
||||
write-host "Searching under" (Get-Item -Path ".\" -Verbose).FullName
|
||||
if (Test-Path "..\..\.vs\bin\MakeXplat.exe" )
|
||||
if (Test-Path "..\..\.vs\bin\makemsix.exe" )
|
||||
{
|
||||
$global:BINDIR="..\..\.vs\bin"
|
||||
}
|
||||
elseif (Test-Path "..\..\.vscode\bin\MakeXplat.exe" )
|
||||
elseif (Test-Path "..\..\.vscode\bin\makemsix.exe" )
|
||||
{
|
||||
$global:BINDIR="..\..\.vscode\bin"
|
||||
}
|
||||
elseif (Test-Path "..\..\build\bin\MakeXplat.exe")
|
||||
elseif (Test-Path "..\..\build\bin\makemsix.exe")
|
||||
{
|
||||
$global:BINDIR="..\..\build\bin"
|
||||
}
|
||||
|
@ -46,10 +46,10 @@ function RunTest([int] $SUCCESSCODE, [string] $PACKAGE, [string] $OPT) {
|
|||
CleanupUnpackFolder
|
||||
$OPTIONS = "unpack -d .\..\unpack -p $PACKAGE $OPT"
|
||||
write-host "------------------------------------------------------"
|
||||
write-host "$BINDIR\MakeXplat.exe $OPTIONS"
|
||||
write-host "$BINDIR\makemsix.exe $OPTIONS"
|
||||
write-host "------------------------------------------------------"
|
||||
|
||||
$p = Start-Process $BINDIR\MakeXplat.exe -ArgumentList "$OPTIONS" -wait -NoNewWindow -PassThru
|
||||
$p = Start-Process $BINDIR\makemsix.exe -ArgumentList "$OPTIONS" -wait -NoNewWindow -PassThru
|
||||
#$p.HasExited
|
||||
$ERRORCODE = $p.ExitCode
|
||||
$a = "{0:x0}" -f $SUCCESSCODE
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
cmake_minimum_required(VERSION 3.4.1)
|
||||
|
||||
include_directories(
|
||||
${include_directories}
|
||||
../../common
|
||||
../../../../src/inc
|
||||
)
|
||||
|
||||
add_library(native-lib SHARED
|
||||
../../common/MobileTests.cpp
|
||||
src/main/cpp/native-lib.cpp
|
||||
)
|
||||
|
||||
# Add our msix library
|
||||
add_library(msix-lib SHARED IMPORTED GLOBAL)
|
||||
set_target_properties(msix-lib PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/src/main/jniLibs/x86/libmsix.so)
|
||||
|
||||
target_link_libraries(native-lib msix-lib android log)
|
|
@ -3,7 +3,7 @@ apply plugin: 'com.android.application'
|
|||
android {
|
||||
compileSdkVersion 26
|
||||
defaultConfig {
|
||||
applicationId "com.microsoft.xplatappxandroid"
|
||||
applicationId "com.microsoft.androidbvt"
|
||||
minSdkVersion 19
|
||||
targetSdkVersion 26
|
||||
versionCode 1
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.microsoft.xplatappxandroid">
|
||||
package="com.microsoft.androidbvt">
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
|
@ -8,7 +8,7 @@
|
|||
#include <android/log.h>
|
||||
|
||||
#include "MobileTests.hpp"
|
||||
#include "AppxWindows.hpp"
|
||||
#include "MSIXWindows.hpp"
|
||||
|
||||
std::string GetStringPathFromJString(JNIEnv* env, jstring jFilePath)
|
||||
{
|
||||
|
@ -23,7 +23,7 @@ void CopyFilesFromAssets(JNIEnv* env, jobject assetManager, std::string filePath
|
|||
if (!subDirectory.empty())
|
||||
{ std::string path = filePath + subDirectory;
|
||||
if (-1 == mkdir(path.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) && errno != EEXIST)
|
||||
{ __android_log_print(ANDROID_LOG_ERROR, "xPlatAppx", "Error creating directory: %s", strerror(errno));
|
||||
{ __android_log_print(ANDROID_LOG_ERROR, "MSIX", "Error creating directory: %s", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,33 +32,33 @@ void CopyFilesFromAssets(JNIEnv* env, jobject assetManager, std::string filePath
|
|||
const char* fileName;
|
||||
int count = 0;
|
||||
while ((fileName = AAssetDir_getNextFileName(assetDir)) != nullptr)
|
||||
{ std::string appxFileName;
|
||||
{ std::string relativeFile;
|
||||
// fileName is relative to the opened dir. AAssetManager_open needs the relative
|
||||
// path from the assets directory.
|
||||
if(!subDirectory.empty())
|
||||
{ appxFileName = subDirectory + "/" + std::string(fileName);
|
||||
if (!subDirectory.empty())
|
||||
{ relativeFile = subDirectory + "/" + std::string(fileName);
|
||||
}
|
||||
else
|
||||
{ appxFileName = std::string(fileName);
|
||||
{ relativeFile = std::string(fileName);
|
||||
}
|
||||
|
||||
// Get asset and copy it.
|
||||
AAsset* appxAsset = AAssetManager_open(manager, appxFileName.c_str(), AASSET_MODE_STREAMING);
|
||||
AAsset* asset = AAssetManager_open(manager, relativeFile.c_str(), AASSET_MODE_STREAMING);
|
||||
int bytesRead = 0;
|
||||
char buffer[BUFSIZ];
|
||||
std::string fileToCreate = filePath + std::string(appxFileName);
|
||||
__android_log_print(ANDROID_LOG_INFO, "xPlatAppx", "File: %s", fileToCreate.c_str());
|
||||
FILE* appxFile = fopen(fileToCreate.c_str(), "w");
|
||||
if(appxFile == nullptr)
|
||||
{ __android_log_print(ANDROID_LOG_ERROR, "xPlatAppx", "File: %s Error: %s", fileToCreate.c_str(), strerror(errno));
|
||||
std::string fileToCreate = filePath + std::string(relativeFile);
|
||||
__android_log_print(ANDROID_LOG_INFO, "MSIX", "File: %s", fileToCreate.c_str());
|
||||
FILE* newFile = fopen(fileToCreate.c_str(), "w");
|
||||
if (newFile == nullptr)
|
||||
{ __android_log_print(ANDROID_LOG_ERROR, "MSIX", "File: %s Error: %s", fileToCreate.c_str(), strerror(errno));
|
||||
}
|
||||
else
|
||||
{ while ((bytesRead = AAsset_read(appxAsset, buffer, BUFSIZ)) > 0)
|
||||
{ fwrite(buffer, bytesRead, 1, appxFile);
|
||||
{ while ((bytesRead = AAsset_read(asset, buffer, BUFSIZ)) > 0)
|
||||
{ fwrite(buffer, bytesRead, 1, newFile);
|
||||
}
|
||||
fclose(appxFile);
|
||||
fclose(newFile);
|
||||
}
|
||||
AAsset_close(appxAsset);
|
||||
AAsset_close(asset);
|
||||
}
|
||||
AAssetDir_close(assetDir);
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ extern "C"
|
|||
JNIEXPORT jstring
|
||||
|
||||
JNICALL
|
||||
Java_com_microsoft_xplatappxandroid_MainActivity_RunTests(JNIEnv* env, jobject /* this */,
|
||||
Java_com_microsoft_androidbvt_MainActivity_RunTests(JNIEnv* env, jobject /* this */,
|
||||
jobject assetManager, jstring jFilePath)
|
||||
{
|
||||
std::string output = "Test failure";
|
|
@ -1,4 +1,4 @@
|
|||
package com.microsoft.xplatappxandroid;
|
||||
package com.microsoft.androidbvt;
|
||||
|
||||
import android.content.res.AssetManager;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
|
@ -25,7 +25,6 @@ public class MainActivity extends AppCompatActivity {
|
|||
// Get assets resource manager
|
||||
mgr = getResources().getAssets();
|
||||
// getFilesDir creates a files directory if not present.
|
||||
// This seems fine to cleaner on where we copy the appxs
|
||||
tv.setText(RunTests(mgr, this.getFilesDir().toString()));
|
||||
|
||||
// Terminate app
|
|
@ -4,7 +4,7 @@
|
|||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context="com.microsoft.xplatappxandroid.MainActivity">
|
||||
tools:context="com.microsoft.androidbvt.MainActivity">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/sample_text"
|
До Ширина: | Высота: | Размер: 3.0 KiB После Ширина: | Высота: | Размер: 3.0 KiB |
До Ширина: | Высота: | Размер: 4.9 KiB После Ширина: | Высота: | Размер: 4.9 KiB |
До Ширина: | Высота: | Размер: 2.0 KiB После Ширина: | Высота: | Размер: 2.0 KiB |
До Ширина: | Высота: | Размер: 2.8 KiB После Ширина: | Высота: | Размер: 2.8 KiB |
До Ширина: | Высота: | Размер: 4.5 KiB После Ширина: | Высота: | Размер: 4.5 KiB |
До Ширина: | Высота: | Размер: 6.9 KiB После Ширина: | Высота: | Размер: 6.9 KiB |
До Ширина: | Высота: | Размер: 6.3 KiB После Ширина: | Высота: | Размер: 6.3 KiB |
До Ширина: | Высота: | Размер: 10 KiB После Ширина: | Высота: | Размер: 10 KiB |
До Ширина: | Высота: | Размер: 9.0 KiB После Ширина: | Высота: | Размер: 9.0 KiB |
До Ширина: | Высота: | Размер: 15 KiB После Ширина: | Высота: | Размер: 15 KiB |
|
@ -0,0 +1,3 @@
|
|||
<resources>
|
||||
<string name="app_name">AndroidBVT</string>
|
||||
</resources>
|
0
test/mobile/xPlatAppxAndroid/gradlew → test/mobile/AndroidBVT/gradlew
поставляемый
Executable file → Normal file
|
@ -1,4 +1,4 @@
|
|||
# xplat\test\mobile
|
||||
# MSIX\test\mobile
|
||||
# Copyright (C) 2017 Microsoft
|
||||
# Created by Phil Smith (psmith@microsoft.com) on 01/29/2018
|
||||
cmake_minimum_required(VERSION 3.4.0 FATAL_ERROR)
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
# xplat\test\mobile\common
|
||||
# MSIX\test\mobile\common
|
||||
# Copyright (C) 2017 Microsoft
|
||||
# Created by Phil Smith (psmith@microsoft.com) on 01/29/2018
|
||||
cmake_minimum_required(VERSION 3.4.0 FATAL_ERROR)
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/../../cmake) # main (top) cmake dir
|
||||
set(LIBRARY_NAME xPlatAppxTestCommon)
|
||||
set(LIBRARY_NAME msixtestcommon)
|
||||
project(${LIBRARY_NAME})
|
||||
|
||||
# Visibility variables for non-win32 platforms
|
||||
|
@ -42,5 +42,5 @@ include_directories(
|
|||
${CMAKE_PROJECT_ROOT}/src/inc
|
||||
)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE xPlatAppx)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE msix)
|
||||
|
||||
|
|