diff --git a/cmake/crypto.cmake b/cmake/crypto.cmake index aa706fdb..fd771b21 100644 --- a/cmake/crypto.cmake +++ b/cmake/crypto.cmake @@ -9,8 +9,9 @@ set( TARGET_INCLUDE_DIRS ${OpenSLL_INCLUDE_PATH} ) set( TARGET_INCLUDE_DIRS_PRIVATE "${TARGET_SOURCE_DIR_TRUE}" "${TARGET_SOURCE_DIR_TRUE}/asn1" "${TARGET_SOURCE_DIR_TRUE}/evp" "${TARGET_SOURCE_DIR_TRUE}/modes") set( TARGET_DEFINES "OPENSSL_THREADS" ) set( TARGET_DEFINES_PRIVATE "${OpenSSL_COMPILER_DEFINES}" ) -set( TARGET_COMPILE_FLAGS "" ) -set( TARGET_COMPILE_FLAGS_PRIVATE "" ) +set( TARGET_COMPILE_FLAGS -fno-rtti -fno-stack-protector -O1 -fno-unwind-tables -fno-asynchronous-unwind-tables + -fno-math-errno -fno-unroll-loops -fmerge-all-constants) +set( TARGET_COMPILE_FLAGS_PRIVATE -ffunction-sections -fdata-sections) set( TARGET_LINK "" ) set( TARGET_LINK_PRIVATE "" ) set( TARGET_SOURCES "" ) @@ -42,6 +43,36 @@ set( CONF " #define OPENSSL_NO_DYNAMIC_ENGINE #define OPENSSL_NO_SCTP #define OPENSSL_NO_EC_NISTP_64_GCC_128 +#define OPENSSL_NO_CAMELLIA +#define OPENSSL_NO_RIPEMD +#define OPENSSL_NO_RC5 +#define OPENSSL_NO_BF +#define OPENSSL_NO_IDEA +#define OPENSSL_NO_ENGINE +#define OPENSSL_NO_DES +#define OPENSSL_NO_MDC2 +#define OPENSSL_NO_SEED +#define OPENSSL_NO_DEPRECATED +#define OPENSSL_NO_DSA +#define OPENSSL_NO_DH +#define OPENSSL_NO_EC +#define OPENSSL_NO_ECDSA +#define OPENSSL_NO_ECDH +#define OPENSSL_NO_WHIRLPOOL +#define OPENSSL_NO_RC4 +#define OPENSSL_NO_RC2 +#define OPENSSL_NO_SSL2 +#define OPENSSL_NO_SSL3 +#define OPENSSL_NO_CAST +#define OPENSSL_NO_CMAC +#define OPENSSL_NO_ZLIB +#define OPENSSL_NO_DGRAM +#define OPENSSL_NO_SOCK +#define OPENSSL_NO_BF +#define OPENSSL_NO_MD4 +#define OPENSSL_NO_CMS +#define OPENSSL_NO_OCSP +#define OPENSSL_NO_SRP ${CONF}" ) file( WRITE "${OpenSLL_INCLUDE_PATH}/openssl/opensslconf.h" "${CONF}" ) @@ -59,19 +90,12 @@ set(TARGET_SOURCES ${XSRC} ${XINC}) # OpenSSL is not the best when it comes to how it handles headers. # Where they are we need to create the projects include dir and copy stuff into it! -if(USE_SHARED_OPENSSL) - message(STATUS "MSIX takes a dynamic dependency on openssl") - add_library(crypto SHARED ${TARGET_SOURCES} ${XSRC_SHARED}) -else() - message(STATUS "MSIX takes a static dependency on openssl") - add_library(crypto STATIC ${TARGET_SOURCES}) -endif() +message(STATUS "MSIX takes a static dependency on openssl") +add_library(crypto STATIC ${TARGET_SOURCES}) target_include_directories( crypto PRIVATE ${TARGET_INCLUDE_DIRS} ${TARGET_INCLUDE_DIRS_PRIVATE} ) target_compile_definitions( crypto PRIVATE ${TARGET_DEFINES} ${TARGET_DEFINES_PRIVATE} ) -target_link_libraries ( crypto PRIVATE ${TARGET_LINK} ${TARGET_LINK_PRIVATE} ) -target_compile_options ( crypto PRIVATE ${TARGET_COMPILE_FLAGS} ${TARGET_COMPILE_FLAGS_PRIVATE} ) +target_compile_options ( crypto PRIVATE ${TARGET_COMPILE_FLAGS} ${TARGET_COMPILE_FLAGS_PRIVATE}) target_include_directories( crypto PUBLIC ${TARGET_INCLUDE_DIRS} ${OpenSLL_INCLUDE_PATH} ${OpenSLL_INCLUDE_PATH}/openssl) target_compile_definitions( crypto PUBLIC ${TARGET_DEFINES} ) -target_link_libraries ( crypto PUBLIC ${TARGET_LINK} ) -target_compile_options ( crypto PUBLIC ${TARGET_COMPILE_FLAGS} ) \ No newline at end of file +target_compile_options ( crypto PUBLIC ${TARGET_COMPILE_FLAGS}) \ No newline at end of file diff --git a/cmake/crypto_sources.cmake b/cmake/crypto_sources.cmake index aaf42b13..c06548de 100644 --- a/cmake/crypto_sources.cmake +++ b/cmake/crypto_sources.cmake @@ -6,7 +6,6 @@ list(APPEND XSRC ${CRYPTO}/cpt_err.c ${CRYPTO}/cryptlib.c ${CRYPTO}/cversion.c - ${CRYPTO}/ebcdic.c ${CRYPTO}/ex_data.c ${CRYPTO}/mem.c ${CRYPTO}/mem_clr.c @@ -105,15 +104,8 @@ list(APPEND XSRC ${CRYPTO}/asn1/x_x509.c ${CRYPTO}/asn1/x_x509a.c - ${CRYPTO}/bf/bf_cfb64.c - ${CRYPTO}/bf/bf_ecb.c - ${CRYPTO}/bf/bf_enc.c - ${CRYPTO}/bf/bf_ofb64.c - ${CRYPTO}/bf/bf_skey.c - ${CRYPTO}/bio/b_dump.c ${CRYPTO}/bio/b_print.c - ${CRYPTO}/bio/b_sock.c ${CRYPTO}/bio/bf_buff.c ${CRYPTO}/bio/bf_nbio.c ${CRYPTO}/bio/bf_null.c @@ -123,21 +115,17 @@ list(APPEND XSRC ${CRYPTO}/bio/bss_acpt.c ${CRYPTO}/bio/bss_bio.c ${CRYPTO}/bio/bss_conn.c - ${CRYPTO}/bio/bss_dgram.c ${CRYPTO}/bio/bss_fd.c ${CRYPTO}/bio/bss_file.c ${CRYPTO}/bio/bss_log.c ${CRYPTO}/bio/bss_mem.c ${CRYPTO}/bio/bss_null.c - ${CRYPTO}/bio/bss_sock.c - # ${CRYPTO}/bio/bf_lbuf.c ${CRYPTO}/bn/bn_add.c ${CRYPTO}/bn/bn_asm.c ${CRYPTO}/bn/bn_blind.c ${CRYPTO}/bn/bn_const.c ${CRYPTO}/bn/bn_ctx.c - ${CRYPTO}/bn/bn_depr.c ${CRYPTO}/bn/bn_div.c ${CRYPTO}/bn/bn_err.c ${CRYPTO}/bn/bn_exp.c @@ -164,42 +152,8 @@ list(APPEND XSRC ${CRYPTO}/buffer/buf_str.c ${CRYPTO}/buffer/buffer.c - ${CRYPTO}/camellia/camellia.c - ${CRYPTO}/camellia/cmll_cbc.c - ${CRYPTO}/camellia/cmll_cfb.c - ${CRYPTO}/camellia/cmll_ctr.c - ${CRYPTO}/camellia/cmll_ecb.c - ${CRYPTO}/camellia/cmll_misc.c - ${CRYPTO}/camellia/cmll_ofb.c - ${CRYPTO}/camellia/cmll_utl.c - - ${CRYPTO}/cast/c_cfb64.c - ${CRYPTO}/cast/c_ecb.c - ${CRYPTO}/cast/c_enc.c - ${CRYPTO}/cast/c_ofb64.c - ${CRYPTO}/cast/c_skey.c - - ${CRYPTO}/cmac/cm_ameth.c - ${CRYPTO}/cmac/cm_pmeth.c - ${CRYPTO}/cmac/cmac.c - - ${CRYPTO}/cms/cms_asn1.c - ${CRYPTO}/cms/cms_att.c - ${CRYPTO}/cms/cms_cd.c - ${CRYPTO}/cms/cms_dd.c - ${CRYPTO}/cms/cms_enc.c - ${CRYPTO}/cms/cms_env.c - ${CRYPTO}/cms/cms_err.c - ${CRYPTO}/cms/cms_ess.c - ${CRYPTO}/cms/cms_io.c - ${CRYPTO}/cms/cms_kari.c - ${CRYPTO}/cms/cms_lib.c - ${CRYPTO}/cms/cms_pwri.c - ${CRYPTO}/cms/cms_sd.c - ${CRYPTO}/cms/cms_smime.c ${CRYPTO}/comp/c_rle.c - ${CRYPTO}/comp/c_zlib.c ${CRYPTO}/comp/comp_err.c ${CRYPTO}/comp/comp_lib.c @@ -211,59 +165,6 @@ list(APPEND XSRC ${CRYPTO}/conf/conf_mod.c ${CRYPTO}/conf/conf_sap.c - ${CRYPTO}/des/cbc_cksm.c - ${CRYPTO}/des/cbc_enc.c - ${CRYPTO}/des/cfb64ede.c - ${CRYPTO}/des/cfb64enc.c - ${CRYPTO}/des/cfb_enc.c - ${CRYPTO}/des/des_enc.c - ${CRYPTO}/des/des_old.c - ${CRYPTO}/des/des_old2.c - ${CRYPTO}/des/ecb3_enc.c - ${CRYPTO}/des/ecb_enc.c - ${CRYPTO}/des/ede_cbcm_enc.c - ${CRYPTO}/des/enc_read.c - ${CRYPTO}/des/enc_writ.c - ${CRYPTO}/des/fcrypt.c - ${CRYPTO}/des/fcrypt_b.c - ${CRYPTO}/des/ofb64ede.c - ${CRYPTO}/des/ofb64enc.c - ${CRYPTO}/des/ofb_enc.c - ${CRYPTO}/des/pcbc_enc.c - ${CRYPTO}/des/qud_cksm.c - ${CRYPTO}/des/rand_key.c - ${CRYPTO}/des/read2pwd.c - ${CRYPTO}/des/rpc_enc.c - ${CRYPTO}/des/set_key.c - ${CRYPTO}/des/str2key.c - ${CRYPTO}/des/xcbc_enc.c - - ${CRYPTO}/dh/dh_ameth.c - ${CRYPTO}/dh/dh_asn1.c - ${CRYPTO}/dh/dh_check.c - ${CRYPTO}/dh/dh_depr.c - ${CRYPTO}/dh/dh_err.c - ${CRYPTO}/dh/dh_gen.c - ${CRYPTO}/dh/dh_kdf.c - ${CRYPTO}/dh/dh_key.c - ${CRYPTO}/dh/dh_lib.c - ${CRYPTO}/dh/dh_pmeth.c - ${CRYPTO}/dh/dh_prn.c - ${CRYPTO}/dh/dh_rfc5114.c - - ${CRYPTO}/dsa/dsa_ameth.c - ${CRYPTO}/dsa/dsa_asn1.c - ${CRYPTO}/dsa/dsa_depr.c - ${CRYPTO}/dsa/dsa_err.c - ${CRYPTO}/dsa/dsa_gen.c - ${CRYPTO}/dsa/dsa_key.c - ${CRYPTO}/dsa/dsa_lib.c - ${CRYPTO}/dsa/dsa_ossl.c - ${CRYPTO}/dsa/dsa_pmeth.c - ${CRYPTO}/dsa/dsa_prn.c - ${CRYPTO}/dsa/dsa_sign.c - ${CRYPTO}/dsa/dsa_vrf.c - ${CRYPTO}/dso/dso_beos.c ${CRYPTO}/dso/dso_dl.c ${CRYPTO}/dso/dso_dlfcn.c @@ -271,67 +172,6 @@ list(APPEND XSRC ${CRYPTO}/dso/dso_lib.c ${CRYPTO}/dso/dso_null.c ${CRYPTO}/dso/dso_openssl.c - # ${CRYPTO}/dso/dso_win32.c <- will use PKI stack instead - - ${CRYPTO}/ec/ec2_mult.c - ${CRYPTO}/ec/ec2_oct.c - ${CRYPTO}/ec/ec2_smpl.c - ${CRYPTO}/ec/ec_ameth.c - ${CRYPTO}/ec/ec_asn1.c - ${CRYPTO}/ec/ec_check.c - ${CRYPTO}/ec/ec_curve.c - ${CRYPTO}/ec/ec_cvt.c - ${CRYPTO}/ec/ec_err.c - ${CRYPTO}/ec/ec_key.c - ${CRYPTO}/ec/ec_lib.c - ${CRYPTO}/ec/ec_mult.c - ${CRYPTO}/ec/ec_oct.c - ${CRYPTO}/ec/ec_pmeth.c - ${CRYPTO}/ec/ec_print.c - ${CRYPTO}/ec/eck_prn.c - ${CRYPTO}/ec/ecp_mont.c - ${CRYPTO}/ec/ecp_nist.c - ${CRYPTO}/ec/ecp_oct.c - ${CRYPTO}/ec/ecp_smpl.c - - ${CRYPTO}/ecdh/ech_err.c - ${CRYPTO}/ecdh/ech_kdf.c - ${CRYPTO}/ecdh/ech_key.c - ${CRYPTO}/ecdh/ech_lib.c - ${CRYPTO}/ecdh/ech_ossl.c - - ${CRYPTO}/ecdsa/ecs_asn1.c - ${CRYPTO}/ecdsa/ecs_err.c - ${CRYPTO}/ecdsa/ecs_lib.c - ${CRYPTO}/ecdsa/ecs_ossl.c - ${CRYPTO}/ecdsa/ecs_sign.c - ${CRYPTO}/ecdsa/ecs_vrf.c - - ${CRYPTO}/engine/eng_all.c - ${CRYPTO}/engine/eng_cnf.c - ${CRYPTO}/engine/eng_cryptodev.c - ${CRYPTO}/engine/eng_ctrl.c - ${CRYPTO}/engine/eng_dyn.c - ${CRYPTO}/engine/eng_err.c - ${CRYPTO}/engine/eng_fat.c - ${CRYPTO}/engine/eng_init.c - ${CRYPTO}/engine/eng_lib.c - ${CRYPTO}/engine/eng_list.c - ${CRYPTO}/engine/eng_openssl.c - ${CRYPTO}/engine/eng_pkey.c - ${CRYPTO}/engine/eng_rdrand.c - ${CRYPTO}/engine/eng_table.c - ${CRYPTO}/engine/tb_asnmth.c - ${CRYPTO}/engine/tb_cipher.c - ${CRYPTO}/engine/tb_dh.c - ${CRYPTO}/engine/tb_digest.c - ${CRYPTO}/engine/tb_dsa.c - ${CRYPTO}/engine/tb_ecdh.c - ${CRYPTO}/engine/tb_ecdsa.c - ${CRYPTO}/engine/tb_pkmeth.c - ${CRYPTO}/engine/tb_rand.c - ${CRYPTO}/engine/tb_rsa.c - ${CRYPTO}/engine/tb_store.c ${CRYPTO}/err/err.c ${CRYPTO}/err/err_all.c @@ -348,20 +188,9 @@ list(APPEND XSRC ${CRYPTO}/evp/e_aes.c ${CRYPTO}/evp/e_aes_cbc_hmac_sha1.c ${CRYPTO}/evp/e_aes_cbc_hmac_sha256.c - ${CRYPTO}/evp/e_bf.c - ${CRYPTO}/evp/e_camellia.c - ${CRYPTO}/evp/e_cast.c - ${CRYPTO}/evp/e_des.c - ${CRYPTO}/evp/e_des3.c - ${CRYPTO}/evp/e_idea.c - ${CRYPTO}/evp/e_null.c + ${CRYPTO}/evp/e_null.c ${CRYPTO}/evp/e_old.c - ${CRYPTO}/evp/e_rc2.c - ${CRYPTO}/evp/e_rc4.c ${CRYPTO}/evp/e_rc4_hmac_md5.c - ${CRYPTO}/evp/e_rc5.c - ${CRYPTO}/evp/e_seed.c - ${CRYPTO}/evp/e_xcbc_d.c ${CRYPTO}/evp/encode.c ${CRYPTO}/evp/evp_acnf.c ${CRYPTO}/evp/evp_cnf.c @@ -373,13 +202,8 @@ list(APPEND XSRC ${CRYPTO}/evp/evp_pkey.c ${CRYPTO}/evp/m_dss.c ${CRYPTO}/evp/m_dss1.c - ${CRYPTO}/evp/m_ecdsa.c - ${CRYPTO}/evp/m_md2.c - ${CRYPTO}/evp/m_md4.c ${CRYPTO}/evp/m_md5.c - ${CRYPTO}/evp/m_mdc2.c ${CRYPTO}/evp/m_null.c - ${CRYPTO}/evp/m_ripemd.c ${CRYPTO}/evp/m_sha.c ${CRYPTO}/evp/m_sha1.c ${CRYPTO}/evp/m_sigver.c @@ -402,26 +226,12 @@ list(APPEND XSRC ${CRYPTO}/hmac/hm_pmeth.c ${CRYPTO}/hmac/hmac.c - ${CRYPTO}/idea/i_cbc.c - ${CRYPTO}/idea/i_cfb64.c - ${CRYPTO}/idea/i_ecb.c - ${CRYPTO}/idea/i_ofb64.c - ${CRYPTO}/idea/i_skey.c - - ${CRYPTO}/krb5/krb5_asn.c - ${CRYPTO}/lhash/lh_stats.c ${CRYPTO}/lhash/lhash.c - ${CRYPTO}/md4/md4_dgst.c - ${CRYPTO}/md4/md4_one.c - ${CRYPTO}/md5/md5_dgst.c ${CRYPTO}/md5/md5_one.c - ${CRYPTO}/mdc2/mdc2_one.c - ${CRYPTO}/mdc2/mdc2dgst.c - ${CRYPTO}/modes/cbc128.c ${CRYPTO}/modes/ccm128.c ${CRYPTO}/modes/cfb128.c @@ -440,13 +250,8 @@ list(APPEND XSRC ${CRYPTO}/ocsp/ocsp_asn.c ${CRYPTO}/ocsp/ocsp_cl.c - ${CRYPTO}/ocsp/ocsp_err.c - ${CRYPTO}/ocsp/ocsp_ext.c ${CRYPTO}/ocsp/ocsp_ht.c ${CRYPTO}/ocsp/ocsp_lib.c - ${CRYPTO}/ocsp/ocsp_prn.c - ${CRYPTO}/ocsp/ocsp_srv.c - ${CRYPTO}/ocsp/ocsp_vfy.c ${CRYPTO}/pem/pem_all.c ${CRYPTO}/pem/pem_err.c @@ -459,7 +264,6 @@ list(APPEND XSRC ${CRYPTO}/pem/pem_sign.c ${CRYPTO}/pem/pem_x509.c ${CRYPTO}/pem/pem_xaux.c - ${CRYPTO}/pem/pvkfmt.c ${CRYPTO}/pkcs12/p12_add.c ${CRYPTO}/pkcs12/p12_asn.c @@ -492,36 +296,13 @@ list(APPEND XSRC ${CRYPTO}/rand/rand_egd.c ${CRYPTO}/rand/rand_err.c ${CRYPTO}/rand/rand_lib.c - ${CRYPTO}/rand/rand_nw.c - ${CRYPTO}/rand/rand_os2.c ${CRYPTO}/rand/rand_unix.c ${CRYPTO}/rand/randfile.c - #${CRYPTO}/rand/rand_win.c <- will use PKI stack instead - - ${CRYPTO}/rc2/rc2_cbc.c - ${CRYPTO}/rc2/rc2_ecb.c - ${CRYPTO}/rc2/rc2_skey.c - ${CRYPTO}/rc2/rc2cfb64.c - ${CRYPTO}/rc2/rc2ofb64.c - - ${CRYPTO}/rc4/rc4_enc.c - ${CRYPTO}/rc4/rc4_skey.c - ${CRYPTO}/rc4/rc4_utl.c - - ${CRYPTO}/rc5/rc5_ecb.c - ${CRYPTO}/rc5/rc5_enc.c - ${CRYPTO}/rc5/rc5_skey.c - ${CRYPTO}/rc5/rc5cfb64.c - ${CRYPTO}/rc5/rc5ofb64.c - - ${CRYPTO}/ripemd/rmd_dgst.c - ${CRYPTO}/ripemd/rmd_one.c ${CRYPTO}/rsa/rsa_ameth.c ${CRYPTO}/rsa/rsa_asn1.c ${CRYPTO}/rsa/rsa_chk.c ${CRYPTO}/rsa/rsa_crpt.c - ${CRYPTO}/rsa/rsa_depr.c ${CRYPTO}/rsa/rsa_eay.c ${CRYPTO}/rsa/rsa_err.c ${CRYPTO}/rsa/rsa_gen.c @@ -538,12 +319,6 @@ list(APPEND XSRC ${CRYPTO}/rsa/rsa_ssl.c ${CRYPTO}/rsa/rsa_x931.c - ${CRYPTO}/seed/seed.c - ${CRYPTO}/seed/seed_cbc.c - ${CRYPTO}/seed/seed_cfb.c - ${CRYPTO}/seed/seed_ecb.c - ${CRYPTO}/seed/seed_ofb.c - ${CRYPTO}/sha/sha1_one.c ${CRYPTO}/sha/sha1dgst.c ${CRYPTO}/sha/sha256.c @@ -551,9 +326,6 @@ list(APPEND XSRC ${CRYPTO}/sha/sha_dgst.c ${CRYPTO}/sha/sha_one.c - ${CRYPTO}/srp/srp_lib.c - ${CRYPTO}/srp/srp_vfy.c - ${CRYPTO}/stack/stack.c ${CRYPTO}/ts/ts_asn1.c @@ -568,17 +340,12 @@ list(APPEND XSRC ${CRYPTO}/ts/ts_rsp_verify.c ${CRYPTO}/ts/ts_verify_ctx.c - ${CRYPTO}/txt_db/txt_db.c - ${CRYPTO}/ui/ui_compat.c ${CRYPTO}/ui/ui_err.c ${CRYPTO}/ui/ui_lib.c ${CRYPTO}/ui/ui_openssl.c ${CRYPTO}/ui/ui_util.c - ${CRYPTO}/whrlpool/wp_block.c - ${CRYPTO}/whrlpool/wp_dgst.c - ${CRYPTO}/x509/by_dir.c ${CRYPTO}/x509/by_file.c ${CRYPTO}/x509/x509_att.c @@ -610,11 +377,9 @@ list(APPEND XSRC ${CRYPTO}/x509v3/pcy_map.c ${CRYPTO}/x509v3/pcy_node.c ${CRYPTO}/x509v3/pcy_tree.c - ${CRYPTO}/x509v3/v3_addr.c ${CRYPTO}/x509v3/v3_akey.c ${CRYPTO}/x509v3/v3_akeya.c ${CRYPTO}/x509v3/v3_alt.c - ${CRYPTO}/x509v3/v3_asid.c ${CRYPTO}/x509v3/v3_bcons.c ${CRYPTO}/x509v3/v3_bitst.c ${CRYPTO}/x509v3/v3_conf.c @@ -643,36 +408,6 @@ list(APPEND XSRC ${CRYPTO}/x509v3/v3err.c ) -list(APPEND XSRC_SHARED - ${OpenSSL_SOURCE_PATH}/engines/e_4758cca.c - ${OpenSSL_SOURCE_PATH}/engines/e_aep.c - ${OpenSSL_SOURCE_PATH}/engines/e_atalla.c - ${OpenSSL_SOURCE_PATH}/engines/e_cswift.c - ${OpenSSL_SOURCE_PATH}/engines/e_gmp.c - ${OpenSSL_SOURCE_PATH}/engines/e_chil.c - ${OpenSSL_SOURCE_PATH}/engines/e_nuron.c - ${OpenSSL_SOURCE_PATH}/engines/e_sureware.c - ${OpenSSL_SOURCE_PATH}/engines/e_ubsec.c - ${OpenSSL_SOURCE_PATH}/engines/e_padlock.c - ${OpenSSL_SOURCE_PATH}/engines/e_capi.c - - ${OpenSSL_SOURCE_PATH}/engines/ccgost/e_gost_err.c - ${OpenSSL_SOURCE_PATH}/engines/ccgost/gost2001.c - ${OpenSSL_SOURCE_PATH}/engines/ccgost/gost2001_keyx.c - ${OpenSSL_SOURCE_PATH}/engines/ccgost/gost89.c - ${OpenSSL_SOURCE_PATH}/engines/ccgost/gost94_keyx.c - ${OpenSSL_SOURCE_PATH}/engines/ccgost/gost_ameth.c - ${OpenSSL_SOURCE_PATH}/engines/ccgost/gost_asn1.c - ${OpenSSL_SOURCE_PATH}/engines/ccgost/gost_crypt.c - ${OpenSSL_SOURCE_PATH}/engines/ccgost/gost_ctl.c - ${OpenSSL_SOURCE_PATH}/engines/ccgost/gost_eng.c - ${OpenSSL_SOURCE_PATH}/engines/ccgost/gosthash.c - ${OpenSSL_SOURCE_PATH}/engines/ccgost/gost_keywrap.c - ${OpenSSL_SOURCE_PATH}/engines/ccgost/gost_md.c - ${OpenSSL_SOURCE_PATH}/engines/ccgost/gost_params.c - ${OpenSSL_SOURCE_PATH}/engines/ccgost/gost_pmeth.c - ${OpenSSL_SOURCE_PATH}/engines/ccgost/gost_sign.c -) ########################################################################################### # INC @@ -680,42 +415,28 @@ list(APPEND XSRC_SHARED list(APPEND XINC ${CRYPTO}/crypto.h ${CRYPTO}/opensslv.h - ${CRYPTO}/ebcdic.h - ${CRYPTO}/symhacks.h + ${CRYPTO}/symhacks.h ${CRYPTO}/ossl_typ.h ${CRYPTO}/aes/aes.h ${CRYPTO}/asn1/asn1.h ${CRYPTO}/asn1/asn1_mac.h ${CRYPTO}/asn1/asn1t.h - ${CRYPTO}/bf/blowfish.h - ${CRYPTO}/bio/bio.h + ${CRYPTO}/bio/bio.h ${CRYPTO}/bn/bn.h ${CRYPTO}/buffer/buffer.h - ${CRYPTO}/camellia/camellia.h - ${CRYPTO}/cast/cast.h - ${CRYPTO}/cmac/cmac.h - ${CRYPTO}/cms/cms.h ${CRYPTO}/comp/comp.h ${CRYPTO}/conf/conf.h ${CRYPTO}/conf/conf_api.h ${CRYPTO}/des/des.h ${CRYPTO}/des/des_old.h - ${CRYPTO}/dh/dh.h - ${CRYPTO}/dsa/dsa.h ${CRYPTO}/dso/dso.h - ${CRYPTO}/ec/ec.h - ${CRYPTO}/ecdh/ecdh.h - ${CRYPTO}/ecdsa/ecdsa.h ${CRYPTO}/engine/engine.h ${CRYPTO}/err/err.h ${CRYPTO}/evp/evp.h ${CRYPTO}/hmac/hmac.h - ${CRYPTO}/idea/idea.h - ${CRYPTO}/krb5/krb5_asn.h ${CRYPTO}/lhash/lhash.h ${CRYPTO}/md4/md4.h ${CRYPTO}/md5/md5.h - ${CRYPTO}/mdc2/mdc2.h ${CRYPTO}/modes/modes.h ${CRYPTO}/objects/objects.h ${CRYPTO}/objects/obj_mac.h @@ -726,23 +447,15 @@ list(APPEND XINC ${CRYPTO}/pkcs7/pkcs7.h ${CRYPTO}/pqueue/pqueue.h ${CRYPTO}/rand/rand.h - ${CRYPTO}/rc2/rc2.h - ${CRYPTO}/rc4/rc4.h ${CRYPTO}/rc5/rc5.h - ${CRYPTO}/ripemd/ripemd.h ${CRYPTO}/rsa/rsa.h ${CRYPTO}/seed/seed.h ${CRYPTO}/sha/sha.h - ${CRYPTO}/srp/srp.h - ${CRYPTO}/srp/srp_grps.h - ${CRYPTO}/srp/srp_lcl.h ${CRYPTO}/stack/stack.h ${CRYPTO}/stack/safestack.h ${CRYPTO}/ts/ts.h - ${CRYPTO}/txt_db/txt_db.h ${CRYPTO}/ui/ui.h ${CRYPTO}/ui/ui_compat.h - ${CRYPTO}/whrlpool/whrlpool.h ${CRYPTO}/x509/x509.h ${CRYPTO}/x509/x509_vfy.h ${CRYPTO}/x509v3/x509v3.h diff --git a/sample/CMakeLists.txt b/sample/CMakeLists.txt index 57c2e126..1b77a474 100644 --- a/sample/CMakeLists.txt +++ b/sample/CMakeLists.txt @@ -6,7 +6,9 @@ cmake_minimum_required(VERSION 3.8.0 FATAL_ERROR) add_subdirectory(ExtractContentsSample) add_subdirectory(BundleSample) add_subdirectory(OverrideStreamSample) +add_subdirectory(OverrideLanguageSample) add_dependencies(ExtractContentsSample msix) add_dependencies(BundleSample msix) add_dependencies(OverrideStreamSample msix) +add_dependencies(OverrideLanguageSample msix) diff --git a/sample/OverrideLanguageSample/CMakeLists.txt b/sample/OverrideLanguageSample/CMakeLists.txt new file mode 100644 index 00000000..e278a084 --- /dev/null +++ b/sample/OverrideLanguageSample/CMakeLists.txt @@ -0,0 +1,27 @@ +# Copyright (C) 2017 Microsoft. All rights reserved. +# See LICENSE file in the project root for full license information. + +cmake_minimum_required(VERSION 3.8.0 FATAL_ERROR) +project (OverrideLanguageSample) + +# Define two variables in order not to repeat ourselves. +set(BINARY_NAME OverrideLanguageSample) + +if(WIN32) + set(DESCRIPTION "OverrideLanguageSample manifest") + configure_file(${CMAKE_PROJECT_ROOT}/manifest.cmakein ${CMAKE_CURRENT_BINARY_DIR}/${BINARY_NAME}.exe.manifest CRLF) + set(MANIFEST ${CMAKE_CURRENT_BINARY_DIR}/${BINARY_NAME}.exe.manifest) +endif() + +add_executable(${BINARY_NAME} + OverrideLanguageSample.cpp + ${MANIFEST} + ) + +target_include_directories(${BINARY_NAME} PRIVATE ${CMAKE_BINARY_DIR}/src/msix) + +add_dependencies(${BINARY_NAME} msix) +if (LINUX OR AOSP) + target_link_libraries(${BINARY_NAME} PRIVATE -latomic) +endif() +target_link_libraries(${BINARY_NAME} PRIVATE msix) diff --git a/sample/OverrideLanguageSample/OverrideLanguageSample.cpp b/sample/OverrideLanguageSample/OverrideLanguageSample.cpp new file mode 100644 index 00000000..fedd0aa3 --- /dev/null +++ b/sample/OverrideLanguageSample/OverrideLanguageSample.cpp @@ -0,0 +1,329 @@ +// +// Copyright (C) 2017 Microsoft. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#include "AppxPackaging.hpp" +#include "MSIXWindows.hpp" + +#include +#include + +#define RETURN_IF_FAILED(a) \ + { HRESULT __hr = a; \ + if (FAILED(__hr)) \ + { return __hr; } \ + } + +// Stripped down ComPtr provided for those platforms that do not already have a ComPtr class. +template +class ComPtr +{ +public: + // default ctor + ComPtr() = default; + ComPtr(T* ptr) : m_ptr(ptr) { InternalAddRef(); } + + // For use instead of ComPtr t(new Foo(...)); given that the class has an Initialize function + template + static HRESULT MakeAndInitialize(T** result, Args&&... args) + { + ComPtr inner(new U()); + RETURN_IF_FAILED(inner->Initialize(std::forward(args)...)); + RETURN_IF_FAILED(inner->QueryInterface(UuidOfImpl::iid, reinterpret_cast(result))); + return S_OK; + } + + // For use instead of ComPtr t(new Foo(...)); + template + static ComPtr Make(Args&&... args) + { + ComPtr result; + result.m_ptr = new U(std::forward(args)...); + return result; + } + + ~ComPtr() { InternalRelease(); } + inline T* operator->() const { return m_ptr; } + inline T* Get() const { return m_ptr; } + + inline T** operator&() + { + InternalRelease(); + return &m_ptr; + } + + T* Detach() + { + T* temp = m_ptr; + m_ptr = nullptr; + return temp; + } + +protected: + T* m_ptr = nullptr; + + inline void InternalAddRef() { if (m_ptr) { m_ptr->AddRef(); } } + inline void InternalRelease() + { + T* temp = m_ptr; + if (temp) + { + m_ptr = nullptr; + temp->Release(); + } + } +}; + +// Or you can use what-ever allocator/deallocator is best for your platform... +LPVOID STDMETHODCALLTYPE MyAllocate(SIZE_T cb) { return std::malloc(cb); } +void STDMETHODCALLTYPE MyFree(LPVOID pv) { std::free(pv); } + +// Helper class to free string buffers obtained from the packaging APIs. +template +class Text +{ +public: + T** operator&() { return &content; } + ~Text() { Cleanup(); } + T* Get() { return content; } + + T* content = nullptr; +protected: + void Cleanup() { if (content) { MyFree(content); content = nullptr; } } +}; + +int Help() +{ + std::cout << std::endl; + std::cout << "Usage:" << std::endl; + std::cout << "------" << std::endl; + std::cout << "\t" << "OverrideLanguageSample " << std::endl; + std::cout << std::endl; + std::cout << "Description:" << std::endl; + std::cout << "------------" << std::endl; + std::cout << "\tSample to show the usage of IMsixFactoryOverrides for MSIX_FACTORY_EXTENSION_APPLICABILITY_LANGUAGES " << std::endl; + std::cout << "\tusing language BCP47 tags from the command line." << std::endl; + std::cout << std::endl; + return 0; +} + +class OverrideLanguages final : public IMsixApplicabilityLanguagesEnumerator +{ +public: + OverrideLanguages(char** languages, int numLanguages) : m_languages(languages), m_numLanguages(numLanguages) {} + + // IUnknown + virtual ULONG STDMETHODCALLTYPE AddRef() override + { + return ++m_ref; + } + + virtual ULONG STDMETHODCALLTYPE Release() override + { + if (--m_ref == 0) + { + delete this; + return 0; + } + return m_ref; + } + + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) noexcept override + { + if (ppvObject == nullptr || *ppvObject != nullptr) + { + return E_INVALIDARG; + } + + *ppvObject = nullptr; + if (riid == UuidOfImpl::iid) + { + *ppvObject = static_cast(reinterpret_cast(this)); + AddRef(); + return S_OK; + } + if (riid == UuidOfImpl::iid) + { + *ppvObject = static_cast(reinterpret_cast(this)); + AddRef(); + return S_OK; + } + return E_NOINTERFACE; + } + + // IMsixApplicabilityLanguagesEnumerator + virtual HRESULT STDMETHODCALLTYPE GetCurrent(LPCSTR *bcp47Language) noexcept override + { + if (m_currentIndex < m_numLanguages) + { + *bcp47Language = m_languages[m_currentIndex]; + return S_OK; + } + else + { + return E_BOUNDS; + } + } + + virtual HRESULT STDMETHODCALLTYPE GetHasCurrent(BOOL *hasCurrent) noexcept override + { + *hasCurrent = (m_currentIndex < m_numLanguages); + return S_OK; + } + + virtual HRESULT STDMETHODCALLTYPE MoveNext(BOOL *hasNext) noexcept override + { + if (m_currentIndex < m_numLanguages) + { + m_currentIndex++; + *hasNext = (m_currentIndex < m_numLanguages); + return S_OK; + } + else + { + return E_BOUNDS; + } + } + +protected: + std::atomic m_ref; + char** m_languages = nullptr; + int m_numLanguages = 0; + int m_currentIndex = 0; +}; + +HRESULT ShowInformationOfPackage(IAppxFile* packageFile) +{ + Text packageName; + RETURN_IF_FAILED(packageFile->GetName(&packageName)); + std::wcout << L"\tName: " << packageName.Get() << std::endl; + + ComPtr factory; + RETURN_IF_FAILED(CoCreateAppxFactoryWithHeap( + MyAllocate, + MyFree, + MSIX_VALIDATION_OPTION::MSIX_VALIDATION_OPTION_SKIPSIGNATURE, + &factory)); + + // Get stream of the package and package reader + ComPtr packageStream; + RETURN_IF_FAILED(packageFile->GetStream(&packageStream)); + ComPtr packageReader; + RETURN_IF_FAILED(factory->CreatePackageReader(packageStream.Get(), &packageReader)); + + // Get information about the package from the manifest + ComPtr manifest; + RETURN_IF_FAILED(packageReader->GetManifest(&manifest)); + ComPtr bundlePackageId; + RETURN_IF_FAILED(manifest->GetPackageId(&bundlePackageId)); + + // Get full name of the bundle + Text fullName; + RETURN_IF_FAILED(bundlePackageId->GetPackageFullName(&fullName)); + std::wcout << L"\tFull Name: " << fullName.Get() << std::endl; + + // Show what are the resources of the package. + ComPtr resourcesEnum; + RETURN_IF_FAILED(manifest->GetResources(&resourcesEnum)); + BOOL hasCurrent = FALSE; + RETURN_IF_FAILED(resourcesEnum->GetHasCurrent(&hasCurrent)); + while (hasCurrent) + { + Text resource; + RETURN_IF_FAILED(resourcesEnum->GetCurrent(&resource)); + std::wcout << L"\tResource: " << resource.Get() << std::endl; + RETURN_IF_FAILED(resourcesEnum->MoveNext(&hasCurrent)); + } + return S_OK; +} + +HRESULT ShowInformationOfBundle(char* bundleName, char** languages, int numLanguages) +{ + std::cout << "File: " << bundleName << std::endl; + + // Initialize the factory with full validation and applicability options. + ComPtr bundleFactory; + RETURN_IF_FAILED(CoCreateAppxBundleFactoryWithHeap( + MyAllocate, + MyFree, + MSIX_VALIDATION_OPTION::MSIX_VALIDATION_OPTION_SKIPSIGNATURE, + MSIX_APPLICABILITY_OPTIONS::MSIX_APPLICABILITY_OPTION_FULL, + &bundleFactory)); + + // Create our object that implements IMsixApplicabilityLanguagesEnumerator + auto overrideLanguages = ComPtr::Make(languages, numLanguages); + + // Get the IMsixFactoryOverrides and set the override. + // Do this before using the factory to create the bundle reader. + ComPtr factoryOverrides; + RETURN_IF_FAILED(bundleFactory->QueryInterface(UuidOfImpl::iid, reinterpret_cast(&factoryOverrides))); + RETURN_IF_FAILED(factoryOverrides->SpecifyExtension(MSIX_FACTORY_EXTENSION_APPLICABILITY_LANGUAGES, overrideLanguages.Get())); + + // Create stream on the file provided. + ComPtr inputStream; + RETURN_IF_FAILED(CreateStreamOnFile(const_cast(bundleName), true, &inputStream)); + + // Now get the bundle reader + ComPtr bundleReader; + RETURN_IF_FAILED(bundleFactory->CreateBundleReader(inputStream.Get(), &bundleReader)); + + // Get basic information about this bundle from the bundle manifest + ComPtr manifestReader; + RETURN_IF_FAILED(bundleReader->GetManifest(&manifestReader)); + ComPtr bundlePackageId; + RETURN_IF_FAILED(manifestReader->GetPackageId(&bundlePackageId)); + + // Get full name of the bundle + Text fullName; + RETURN_IF_FAILED(bundlePackageId->GetPackageFullName(&fullName)); + std::wcout << L"Full Name: " << fullName.Get() << std::endl; + + // A bundle with the MSIX_FACTORY_EXTENSION_APPLICABILITY_LANGUAGES override + // will only show the packages that are applicable to the list of languages + // specified. Get the applicable packages by calling GetPayloadPackages. + ComPtr applicablePackages; + RETURN_IF_FAILED(bundleReader->GetPayloadPackages(&applicablePackages)); + + BOOL hasCurrent = FALSE; + RETURN_IF_FAILED(applicablePackages->GetHasCurrent(&hasCurrent)); + std::wcout << L"Applicable Packages: " << std::endl; + while (hasCurrent) + { + ComPtr applicablePackage; + RETURN_IF_FAILED(applicablePackages->GetCurrent(&applicablePackage)); + RETURN_IF_FAILED(ShowInformationOfPackage(applicablePackage.Get())); + std::wcout << std::endl; + RETURN_IF_FAILED(applicablePackages->MoveNext(&hasCurrent)); + } + + return S_OK; +} + +int main(int argc, char* argv[]) +{ + if (argc < 3) + { + return Help(); + } + + HRESULT hr = ShowInformationOfBundle(argv[1], argv + 2, argc - 2); + + if (FAILED(hr)) + { + std::cout << "Error: " << std::hex << hr << " while reading the bundle" << std::endl; + Text text; + auto logResult = GetLogTextUTF8(MyAllocate, &text); + if (0 == logResult) + { + std::cout << "LOG:" << std::endl << text.content << std::endl; + } + else + { + std::cout << "UNABLE TO GET LOG WITH HR=" << std::hex << logResult << std::endl; + } + } + + return 0; +} + diff --git a/src/inc/Applicability.hpp b/src/inc/Applicability.hpp index aa1c8232..5ad09902 100644 --- a/src/inc/Applicability.hpp +++ b/src/inc/Applicability.hpp @@ -50,6 +50,9 @@ namespace MSIX { Applicability(MSIX_APPLICABILITY_OPTIONS applicabilityFlags) : m_applicabilityFlags(applicabilityFlags) {} + void InitializeLanguages(); + void InitializeLanguages(IMsixApplicabilityLanguagesEnumerator* languagesEnumerator); + void AddPackageIfApplicable(ComPtr& reader, std::string& packageName, const std::vector& packageLanguages, APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE packageType, bool hasQualifiedResources); @@ -65,5 +68,6 @@ namespace MSIX { std::vector>> m_variantFormPackages; std::vector>> m_extraApplicationPackages; MSIX_APPLICABILITY_OPTIONS m_applicabilityFlags = MSIX_APPLICABILITY_OPTIONS::MSIX_APPLICABILITY_OPTION_FULL; + std::vector m_languages; }; } \ No newline at end of file diff --git a/src/inc/AppxFactory.hpp b/src/inc/AppxFactory.hpp index 1bd94a80..109b4ee9 100644 --- a/src/inc/AppxFactory.hpp +++ b/src/inc/AppxFactory.hpp @@ -71,5 +71,6 @@ namespace MSIX { std::vector m_resourcesVector; MSIX_APPLICABILITY_OPTIONS m_applicabilityFlags; ComPtr m_streamFactory; + ComPtr m_applicabilityLanguagesEnumerator; }; } \ No newline at end of file diff --git a/src/inc/AppxPackaging.hpp b/src/inc/AppxPackaging.hpp index c1d883f9..c1742416 100644 --- a/src/inc/AppxPackaging.hpp +++ b/src/inc/AppxPackaging.hpp @@ -1121,6 +1121,7 @@ interface IMsixElement; interface IMsixElementEnumerator; interface IMsixFactoryOverrides; interface IMsixStreamFactory; +interface IMsixApplicabilityLanguagesEnumerator; #ifndef __IMsixDocumentElement_INTERFACE_DEFINED__ #define __IMsixDocumentElement_INTERFACE_DEFINED__ @@ -1177,6 +1178,7 @@ EXTERN_C DECLSPEC_SELECTANY const IID IID_IMsixFactoryOverrides; enum MSIX_FACTORY_EXTENSION { MSIX_FACTORY_EXTENSION_STREAM_FACTORY = 0x1, + MSIX_FACTORY_EXTENSION_APPLICABILITY_LANGUAGES = 0x2, } MSIX_FACTORY_EXTENSION; // {0acedbdb-57cd-4aca-8cee-33fa52394316} @@ -1203,6 +1205,25 @@ EXTERN_C DECLSPEC_SELECTANY const IID IID_IMsixStreamFactory; #endif /* __IMsixStreamFactory_INTERFACE_DEFINED__ */ +#ifndef __IMsixApplicabilityLanguagesEnumerator_INTERFACE_DEFINED__ +#define __IMsixApplicabilityLanguagesEnumerator_INTERFACE_DEFINED__ + +EXTERN_C DECLSPEC_SELECTANY const IID IID_IMsixApplicabilityLanguagesEnumerator; + + // {BFC4655A-BE7A-456A-BC4E-2AF9481E8432} + interface IMsixApplicabilityLanguagesEnumerator : public IUnknown + { + virtual HRESULT STDMETHODCALLTYPE GetCurrent( + /* [retval][string][out] */ LPCSTR *bcp47Language) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetHasCurrent( + /* [retval][out] */ BOOL *hasCurrent) = 0; + + virtual HRESULT STDMETHODCALLTYPE MoveNext( + /* [retval][out] */ BOOL *hasNext) = 0; + }; + +#endif /* __IMsixApplicabilityLanguagesEnumerator_INTERFACE_DEFINED__ */ extern "C++" { typedef /* [v1_enum] */ @@ -1386,5 +1407,6 @@ SpecializeUuidOfImpl(IMsixElement); SpecializeUuidOfImpl(IMsixElementEnumerator); SpecializeUuidOfImpl(IMsixFactoryOverrides); SpecializeUuidOfImpl(IMsixStreamFactory); +SpecializeUuidOfImpl(IMsixApplicabilityLanguagesEnumerator); #endif //__appxpackaging_hpp__ \ No newline at end of file diff --git a/src/inc/Exceptions.hpp b/src/inc/Exceptions.hpp index 99aab7c5..ff2db925 100644 --- a/src/inc/Exceptions.hpp +++ b/src/inc/Exceptions.hpp @@ -13,90 +13,10 @@ #include "Log.hpp" #include "MSIXWindows.hpp" - -#ifdef USING_XERCES - #include "xercesc/util/XMLException.hpp" - #include "xercesc/dom/DOMException.hpp" -#endif +#include "MsixErrors.hpp" namespace MSIX { - static const std::uint32_t ERROR_FACILITY = 0x8BAD0000; // Facility 2989 - static const std::uint32_t XML_FACILITY = ERROR_FACILITY + 0x1000; // XML exceptions: 0x8BAD1000 + XMLException error code - static const std::uint32_t XERCES_SAX_FACILITY = ERROR_FACILITY + 0x2000; // Xerces XMLException. 0x8BAD1000 + XMLException error code - static const std::uint32_t XERCES_XML_FACILITY = ERROR_FACILITY + 0x3000; - static const std::uint32_t XERCES_DOM_FACILITY = ERROR_FACILITY + 0x4000; - - // defines error codes - enum class Error : std::uint32_t - { - // - // Win32 error codes - // - OK = 0x00000000, - NotImplemented = 0x80004001, - NoInterface = 0x80004002, - Unexpected = 0x8000ffff, - FileNotFound = 0x80070002, - OutOfMemory = 0x8007000E, - NotSupported = 0x80070032, - InvalidParameter = 0x80070057, - Stg_E_Invalidpointer = 0x80030009, - - // - // msix specific error codes - // - - // Basic file errors - FileOpen = ERROR_FACILITY + 0x0001, - FileSeek = ERROR_FACILITY + 0x0002, - FileRead = ERROR_FACILITY + 0x0003, - FileWrite = ERROR_FACILITY + 0x0003, - FileCreateDirectory = ERROR_FACILITY + 0x0004, - FileSeekOutOfRange = ERROR_FACILITY + 0x0005, - - // Zip format errors - ZipCentralDirectoryHeader = ERROR_FACILITY + 0x0011, - ZipLocalFileHeader = ERROR_FACILITY + 0x0012, - Zip64EOCDRecord = ERROR_FACILITY + 0x0013, - Zip64EOCDLocator = ERROR_FACILITY + 0x0014, - ZipEOCDRecord = ERROR_FACILITY + 0x0015, - ZipHiddenData = ERROR_FACILITY + 0x0016, - ZipBadExtendedData = ERROR_FACILITY + 0x0017, - - // Inflate errors - InflateInitialize = ERROR_FACILITY + 0x0021, - InflateRead = ERROR_FACILITY + 0x0022, - InflateCorruptData = ERROR_FACILITY + 0x0023, - - // 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 - SignatureInvalid = ERROR_FACILITY + 0x0041, - CertNotTrusted = ERROR_FACILITY + 0x0042, - PublisherMismatch = ERROR_FACILITY + 0x0043, - - // Blockmap semantic errors - BlockMapSemanticError = ERROR_FACILITY + 0x0051, - - // AppxManifest semantic errors - AppxManifestSemanticError = ERROR_FACILITY + 0x0061, - - // Bundle errors - PackageIsBundle = ERROR_FACILITY + 0x0071, - - // XML parsing errors - XmlWarning = XML_FACILITY + 0x0001, - XmlError = XML_FACILITY + 0x0002, - XmlFatal = XML_FACILITY + 0x0003, - }; - // Defines a common exception type to throw in exceptional cases. DO NOT USE FOR FLOW CONTROL! // Throwing MSIX::Exception will break into the debugger on chk builds to aid debugging class Exception : public std::exception @@ -133,27 +53,6 @@ namespace MSIX { } }; -#ifdef USING_XERCES - // Provides an ABI exception boundary with parameter validation - #define CATCH_RETURN() \ - catch (const XERCES_CPP_NAMESPACE::XMLException& e) \ - { return static_cast(MSIX::XERCES_XML_FACILITY) + \ - static_cast(e.getCode()); \ - } \ - catch (const XERCES_CPP_NAMESPACE::DOMException& e) \ - { return static_cast(MSIX::XERCES_DOM_FACILITY) + \ - static_cast(e.code); \ - } \ - catch (MSIX::Exception& e) \ - { return static_cast(e.Code()); \ - } \ - catch (std::bad_alloc&) \ - { return static_cast(MSIX::Error::OutOfMemory); \ - } \ - catch (...) \ - { return static_cast(MSIX::Error::Unexpected); \ - } -#else // Provides an ABI exception boundary with parameter validation #define CATCH_RETURN() \ catch (MSIX::Exception& e) \ @@ -165,7 +64,6 @@ namespace MSIX { catch (...) \ { return static_cast(MSIX::Error::Unexpected); \ } -#endif template #ifdef WIN32 diff --git a/src/inc/FileStream.hpp b/src/inc/FileStream.hpp index 7b05a7df..7dab9850 100644 --- a/src/inc/FileStream.hpp +++ b/src/inc/FileStream.hpp @@ -10,6 +10,7 @@ #include "Exceptions.hpp" #include "StreamBase.hpp" +#include "UnicodeConversion.hpp" namespace MSIX { class FileStream final : public StreamBase @@ -38,6 +39,28 @@ namespace MSIX { m_size = end.u.LowPart; } + FileStream(const std::wstring& name, Mode mode) + { + m_name = utf16_to_utf8(name); + #ifdef WIN32 + static const wchar_t* modes[] = { L"rb", L"wb", L"ab", L"r+b", L"w+b", L"a+b" }; + errno_t err = _wfopen_s(&m_file, name.c_str(), modes[mode]); + std::wostringstream builder; + builder << L"file: '" << name << L"' does not exist."; + ThrowErrorIfNot(Error::FileOpen, (err==0), "change this"); + #else + static const char* modes[] = { "rb", "wb", "ab", "r+b", "w+b", "a+b" }; + m_file = std::fopen(m_name.c_str(), modes[mode]); + ThrowErrorIfNot(Error::FileOpen, (m_file), m_name.c_str()); + #endif + // Get size of the file + LARGE_INTEGER start = { 0 }; + ULARGE_INTEGER end = { 0 }; + ThrowHrIfFailed(Seek(start, StreamBase::Reference::END, &end)); + ThrowHrIfFailed(Seek(start, StreamBase::Reference::START, nullptr)); + m_size = end.u.LowPart; + } + virtual ~FileStream() override { Close(); diff --git a/src/inc/MSIXWindows.hpp b/src/inc/MSIXWindows.hpp index 7b60190d..54cd5c52 100644 --- a/src/inc/MSIXWindows.hpp +++ b/src/inc/MSIXWindows.hpp @@ -112,6 +112,16 @@ typedef const WCHAR* LPCWSTR; #endif + #ifndef _LPSTR_DEFINED + #define _LPSTR_DEFINED + typedef char* LPSTR; + #endif + + #ifndef _LPCSTR_DEFINED + #define _LPCSTR_DEFINED + typedef const char* LPCSTR; + #endif + #ifndef _BYTE_DEFINED #define _BYTE_DEFINED typedef unsigned char BYTE; @@ -254,6 +264,10 @@ #define E_NOTIMPL 0x80004001 #endif + #ifndef E_BOUNDS + #define E_BOUNDS 0x8000000b + #endif + #if !defined (_SYS_GUID_OPERATORS_) #define _SYS_GUID_OPERATORS_ diff --git a/src/inc/MsixErrors.hpp b/src/inc/MsixErrors.hpp new file mode 100644 index 00000000..d68d4e48 --- /dev/null +++ b/src/inc/MsixErrors.hpp @@ -0,0 +1,81 @@ +// +// Copyright (C) 2017 Microsoft. All rights reserved. +// See LICENSE file in the project root for full license information. +// +#pragma once + +namespace MSIX { + + static const std::uint32_t ERROR_FACILITY = 0x8BAD0000; // Facility 2989 + static const std::uint32_t XML_FACILITY = ERROR_FACILITY + 0x1000; // XML exceptions: 0x8BAD1000 + XMLException error code + + // defines error codes + enum class Error : std::uint32_t + { + // + // Win32 error codes + // + OK = 0x00000000, + NotImplemented = 0x80004001, + NoInterface = 0x80004002, + Unexpected = 0x8000ffff, + FileNotFound = 0x80070002, + OutOfMemory = 0x8007000E, + NotSupported = 0x80070032, + InvalidParameter = 0x80070057, + Stg_E_Invalidpointer = 0x80030009, + + // + // msix specific error codes + // + + // Basic file errors + FileOpen = ERROR_FACILITY + 0x0001, + FileSeek = ERROR_FACILITY + 0x0002, + FileRead = ERROR_FACILITY + 0x0003, + FileWrite = ERROR_FACILITY + 0x0003, + FileCreateDirectory = ERROR_FACILITY + 0x0004, + FileSeekOutOfRange = ERROR_FACILITY + 0x0005, + + // Zip format errors + ZipCentralDirectoryHeader = ERROR_FACILITY + 0x0011, + ZipLocalFileHeader = ERROR_FACILITY + 0x0012, + Zip64EOCDRecord = ERROR_FACILITY + 0x0013, + Zip64EOCDLocator = ERROR_FACILITY + 0x0014, + ZipEOCDRecord = ERROR_FACILITY + 0x0015, + ZipHiddenData = ERROR_FACILITY + 0x0016, + ZipBadExtendedData = ERROR_FACILITY + 0x0017, + + // Inflate errors + InflateInitialize = ERROR_FACILITY + 0x0021, + InflateRead = ERROR_FACILITY + 0x0022, + InflateCorruptData = ERROR_FACILITY + 0x0023, + + // 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 + SignatureInvalid = ERROR_FACILITY + 0x0041, + CertNotTrusted = ERROR_FACILITY + 0x0042, + PublisherMismatch = ERROR_FACILITY + 0x0043, + + // Blockmap semantic errors + BlockMapSemanticError = ERROR_FACILITY + 0x0051, + + // AppxManifest semantic errors + AppxManifestSemanticError = ERROR_FACILITY + 0x0061, + + // Bundle errors + PackageIsBundle = ERROR_FACILITY + 0x0071, + + // XML parsing errors + XmlWarning = XML_FACILITY + 0x0001, + XmlError = XML_FACILITY + 0x0002, + XmlFatal = XML_FACILITY + 0x0003, + }; +} diff --git a/src/inc/ObjectBase.hpp b/src/inc/ObjectBase.hpp index 714dc2a4..671bd449 100644 --- a/src/inc/ObjectBase.hpp +++ b/src/inc/ObjectBase.hpp @@ -14,143 +14,54 @@ namespace MSIX { namespace Meta { ////////////////////////////////////////////////////////////////////////////////////////////// // Basic Validation Policies // ////////////////////////////////////////////////////////////////////////////////////////////// -template -class NoValidation -{ -public: - static inline void Validate(std::size_t, Derived*) { } -}; -template -class InvalidFieldValidation // If the field has size>0, then this field should NOT be read. -{ -public: - static void Validate(std::size_t, Derived* self) { - ThrowErrorIf(Error::Unexpected, self->Size() != 0, "Unexpected data encountered."); - } -}; - -template -class ExactValueValidation // there is exactly one value that this field is allowed to be -{ -public: - static void Validate(std::size_t, Derived* self) { - ThrowErrorIfNot(Error::InvalidParameter, spec == self->value, "Incorrect value specified at field."); - } -}; +// there is exactly one value that this field is allowed to be +template +static void ExactValueValidation(T value, T spec) { + ThrowErrorIfNot(Error::InvalidParameter, spec == value, "Incorrect value specified at field."); +} -template -class NotValueValidation // there is exactly one value that this field is not allowed to be -{ -public: - static void Validate(std::size_t, Derived* self) { - ThrowErrorIf(Error::InvalidParameter, spec == self->value, "Incorrect value specified at field."); - } -}; +// there is exactly one value that this field is not allowed to be +template +static void NotValueValidation(T value, T spec) { + ThrowErrorIf(Error::InvalidParameter, spec == value, "Incorrect value specified at field."); +} -template -class OnlyEitherValueValidation // there are exactly two values that this field is allowed to be +// there are exactly two values that this field is allowed to be +template +static void OnlyEitherValueValidation(T value, T spec1, T spec2) { -public: - static void Validate(std::size_t, Derived* self) - { - ThrowErrorIf(Error::InvalidParameter, - spec1 != self->value && spec2 != self->value, - "Incorrect value specified at field."); - } -}; - -////////////////////////////////////////////////////////////////////////////////////////////// -// Advanced Validation Policies // -////////////////////////////////////////////////////////////////////////////////////////////// - -// An injectable validator type supports parent-injectable validation. This is used in -// concert with the InjectedValidation type, which is specified as a validator of either -// FieldBase or FieldNBytes -class InjectableValidator -{ -public: - virtual void ValidateField(size_t field) - { - // If you're here and you didn't override, you either have a bug in your - // type list definition or your derived type didn't wire-up the specified - // field's parent to point at your type's instance. - UNEXPECTED; - } -}; - -template -class InjectedValidation // derived type will rely on in situ parent-scope validation -{ -public: - static void Validate(std::size_t field, Derived* self) { self->parent->ValidateField(field); } - - InjectableValidator* parent = nullptr; -}; + ThrowErrorIf(Error::InvalidParameter, + spec1 != value && spec2 != value, + "Incorrect value specified at field."); +} ////////////////////////////////////////////////////////////////////////////////////////////// // Base type for individual serializable/deserializable fields // ////////////////////////////////////////////////////////////////////////////////////////////// -template > -class FieldBase : public Validation +template +class FieldBase { public: FieldBase() = default; - - void Write(std::size_t index, const ComPtr& stream) - { - StreamBase::Write(stream, &value); - } - - void Read(std::size_t index, const ComPtr& stream) - { - StreamBase::Read(stream, &value); - this->Validate(index, static_cast(this)); - } - + size_t Size() { return sizeof(T); } T value; }; -// Simple 2, 4, and 8 byte fields with no validation -class Field2Bytes final : public FieldBase { }; -class Field4Bytes final : public FieldBase { }; -class Field8Bytes final : public FieldBase { }; +// Simple 2, 4, and 8 byte fields +class Field2Bytes final : public FieldBase { }; +class Field4Bytes final : public FieldBase { }; +class Field8Bytes final : public FieldBase { }; // variable length field. -template > -class VarLenField : public FieldBase, Validation> +class FieldNBytes : public FieldBase> { public: size_t Size() { return this->value.size(); } - - void Write(std::size_t index, const ComPtr& stream) - { - if (this->value.size() != 0) - { ThrowHrIfFailed(stream->Write( - reinterpret_cast(this->value.data()), - static_cast(this->value.size()), - nullptr - )); - } - } - - void Read(std::size_t index, const ComPtr& stream) - { - if (this->value.size() != 0) - { ThrowHrIfFailed(stream->Read( - reinterpret_cast(this->value.data()), - static_cast(this->value.size()), - nullptr - )); - } - this->Validate(index, static_cast(this)); - } }; -class FieldNBytes final : public VarLenField {}; - ////////////////////////////////////////////////////////////////////////////////////////////// // Heterogeneous collection of types that are operated on as a compile-time vector // ////////////////////////////////////////////////////////////////////////////////////////////// @@ -177,8 +88,8 @@ public: ////////////////////////////////////////////////////////////////////////////////////////////// // Aggregated set of types // ////////////////////////////////////////////////////////////////////////////////////////////// -template -class StructuredObject : public InjectableValidator, public TypeList +template +class StructuredObject : public TypeList { public: size_t Size() @@ -189,26 +100,6 @@ public: }, result); return result; } - - void Write(const ComPtr& s) - { - this->for_each([](auto& field, std::size_t index, const ComPtr& stream) - { field.Write(index, stream); - }, s); - } - - void Read(const ComPtr& s) - { - this->for_each([](auto& field, std::size_t index, const ComPtr& stream) - { field.Read(index, stream); - }, s); - static_cast(this)->Validate(); - } - - void Validate() {} // default structured object validation is no validation. - - template - void ConfigureField() { std::get(this->fields).parent = static_cast(this); } }; } /* namespace Meta */ } /* namespace MSIX */ \ No newline at end of file diff --git a/src/msix/ApplicabilityCommon.cpp b/src/msix/ApplicabilityCommon.cpp index 0bf62ce9..e3615c3d 100644 --- a/src/msix/ApplicabilityCommon.cpp +++ b/src/msix/ApplicabilityCommon.cpp @@ -136,6 +136,25 @@ namespace MSIX { return result; } + void Applicability::InitializeLanguages() + { + m_languages = GetLanguages(); + } + + void Applicability::InitializeLanguages(IMsixApplicabilityLanguagesEnumerator* languagesEnumerator) + { + BOOL hasNext = FALSE; + ThrowHrIfFailed(languagesEnumerator->GetHasCurrent(&hasNext)); + while (hasNext) + { + LPCSTR language = nullptr; + ThrowHrIfFailed(languagesEnumerator->GetCurrent(&language)); + m_languages.push_back(std::string(language)); + + ThrowHrIfFailed(languagesEnumerator->MoveNext(&hasNext)); + } + } + void Applicability::AddPackageIfApplicable(ComPtr& reader, std::string& packageName, const std::vector& packageLanguages, APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE packageType, bool hasQualifiedResources) { @@ -158,7 +177,7 @@ namespace MSIX { bool hasMatch = false; bool hasVariantMatch = false; - for (auto& systemLanguage : GetLanguages()) + for (auto& systemLanguage : m_languages) { for (auto& packageLanguage : packageLanguages) { diff --git a/src/msix/AppxFactory.cpp b/src/msix/AppxFactory.cpp index d3614c62..60a1f25c 100644 --- a/src/msix/AppxFactory.cpp +++ b/src/msix/AppxFactory.cpp @@ -186,6 +186,10 @@ namespace MSIX { { ThrowHrIfFailed(extension->QueryInterface(UuidOfImpl::iid, reinterpret_cast(&m_streamFactory))); } + else if (name == MSIX_FACTORY_EXTENSION_APPLICABILITY_LANGUAGES) + { + ThrowHrIfFailed(extension->QueryInterface(UuidOfImpl::iid, reinterpret_cast(&m_applicabilityLanguagesEnumerator))); + } else { return static_cast(Error::InvalidParameter); @@ -205,6 +209,13 @@ namespace MSIX { *extension = m_streamFactory.As().Detach(); } } + else if (name == MSIX_FACTORY_EXTENSION_APPLICABILITY_LANGUAGES) + { + if (m_applicabilityLanguagesEnumerator.Get() != nullptr) + { + *extension = m_applicabilityLanguagesEnumerator.As().Detach(); + } + } else { return static_cast(Error::InvalidParameter); diff --git a/src/msix/AppxPackageObject.cpp b/src/msix/AppxPackageObject.cpp index 11121a9f..d199c06b 100644 --- a/src/msix/AppxPackageObject.cpp +++ b/src/msix/AppxPackageObject.cpp @@ -216,6 +216,21 @@ namespace MSIX { auto appxFactory = m_factory.As(); Applicability applicability(applicabilityFlags); + + auto factoryOverrides = m_factory.As(); + ComPtr applicabilityLanguagesUnk; + ThrowHrIfFailed(factoryOverrides->GetCurrentSpecifiedExtension(MSIX_FACTORY_EXTENSION_APPLICABILITY_LANGUAGES, &applicabilityLanguagesUnk)); + + if (applicabilityLanguagesUnk.Get() != nullptr) + { + auto applicabilityLanguagesEnumerator = applicabilityLanguagesUnk.As(); + applicability.InitializeLanguages(applicabilityLanguagesEnumerator.Get()); + } + else + { + applicability.InitializeLanguages(); + } + for (const auto& package : bundleInfo->GetPackages()) { auto bundleInfoInternal = package.As(); @@ -232,7 +247,6 @@ namespace MSIX { // We should only do this for flat bundles. If we do it for normal bundles and the user specify a // stream factory we will basically unpack any package the user wants with the same name as the package // we are looking, which sounds dangerous. - auto factoryOverrides = m_factory.As(); ComPtr streamFactoryUnk; ThrowHrIfFailed(factoryOverrides->GetCurrentSpecifiedExtension(MSIX_FACTORY_EXTENSION_STREAM_FACTORY, &streamFactoryUnk)); diff --git a/src/msix/AppxPackaging_i.cpp b/src/msix/AppxPackaging_i.cpp index a15be45c..b62b55fb 100644 --- a/src/msix/AppxPackaging_i.cpp +++ b/src/msix/AppxPackaging_i.cpp @@ -78,6 +78,7 @@ MIDL_PUBLIC_GUID(IID, IID_IMsixElement,0x5B6786FF,0x6145,0x4F0E,0xB8,0xC9,0x8E,0 MIDL_PUBLIC_GUID(IID, IID_IMsixElementEnumerator,0x7E7EA105,0xA4F9,0x4C12,0x9E,0xFA,0x98,0xEF,0x18,0x95,0x41,0x8A); MIDL_PUBLIC_GUID(IID, IID_IMsixFactoryOverrides,0x0ACEDBDB,0x57CD,0x4ACA,0X8C,0XEE,0X33,0XFA,0X52,0X39,0X43,0X16); MIDL_PUBLIC_GUID(IID, IID_IMsixStreamFactory,0XC74F4821,0X3B82,0X4AD5,0X98,0XEA,0X3D,0X52,0X68,0X1A,0XFF,0X56); +MIDL_PUBLIC_GUID(IID, IID_IMsixApplicabilityLanguagesEnumerator,0xbfc4655a,0xbe7a,0x456a,0xbc,0x4e,0x2a,0xf9,0x48,0x1e,0x84,0x32); // internal interfaces. MIDL_DEFINE_GUID(IID, IID_IPackage, 0x51B2C456,0xAAA9,0x46D6,0x8E,0xC9,0x29,0x82,0x20,0x55,0x91,0x89); diff --git a/src/msix/CMakeLists.txt b/src/msix/CMakeLists.txt index b8441795..6f67f80a 100644 --- a/src/msix/CMakeLists.txt +++ b/src/msix/CMakeLists.txt @@ -98,6 +98,7 @@ else() "IID_IMsixElementEnumerator" "IID_IMsixFactoryOverrides" "IID_IMsixStreamFactory" + "IID_IMsixApplicabilityLanguagesEnumerator" ) if((IOS) OR (MACOS)) # on Apple platforms you can explicitly define which symbols are exported @@ -189,6 +190,7 @@ include(msix_resources) set(LIB_PUBLIC_HEADERS ../inc/AppxPackaging.hpp ../inc/MSIXWindows.hpp + ../inc/MsixErrors.hpp ) # Bundle specific files @@ -228,6 +230,7 @@ add_library(${PROJECT_NAME} SHARED # Copy out public headers to /src/msix configure_file(../inc/MSIXWindows.hpp ${CMAKE_CURRENT_BINARY_DIR}/MSIXWindows.hpp ) configure_file(../inc/AppxPackaging.hpp ${CMAKE_CURRENT_BINARY_DIR}/AppxPackaging.hpp) +configure_file(../inc/MsixErrors.hpp ${CMAKE_CURRENT_BINARY_DIR}/MsixErrors.hpp) # Linker and includes # Include MSIX headers @@ -236,8 +239,9 @@ target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_PROJECT_ROOT}/src/inc if(WIN32) + string(REPLACE "/GR" " " CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") set_target_properties(${PROJECT_NAME} PROPERTIES - COMPILE_FLAGS "/source-charset:utf-8" + COMPILE_FLAGS "/source-charset:utf-8 /Gw /GL /GR-" VS_WINRT_COMPONENT TRUE) # Using /DELAYLOAD as linker option will use a helper funtion provided by # Visual C++ that will load the dll at runtime by calling LoadLibrary and GetProcAddress. @@ -249,7 +253,7 @@ if(WIN32) "/DELAYLOAD:api-ms-win-core-winrt-string-l1-1-0.dll" "/DELAYLOAD:api-ms-win-core-winrt-l1-1-0.dll") string(REPLACE ";" " " DELAYFLAGS "${DELAYFLAGS}") - set_property(TARGET ${PROJECT_NAME} APPEND_STRING PROPERTY LINK_FLAGS "${DELAYFLAGS}") + set_property(TARGET ${PROJECT_NAME} APPEND_STRING PROPERTY LINK_FLAGS "${DELAYFLAGS} /LTCG") if(USE_STATIC_MSVC) if(CMAKE_BUILD_TYPE MATCHES Debug) set_property(TARGET ${PROJECT_NAME} APPEND_STRING PROPERTY LINK_FLAGS " /NODEFAULTLIB:MSVCRTD") @@ -363,5 +367,9 @@ endif() if(OpenSSL_FOUND) # include the libraries needed to use OpenSSL target_include_directories(${PROJECT_NAME} PRIVATE ${OpenSLL_INCLUDE_PATH}) - target_link_libraries(${PROJECT_NAME} PRIVATE crypto) -endif() + if((IOS) OR (MACOS)) + target_link_libraries(${PROJECT_NAME} PRIVATE crypto -Wl,-dead_strip) + else() + target_link_libraries(${PROJECT_NAME} PRIVATE crypto -Wl,--gc-sections) + endif() +endif() \ No newline at end of file diff --git a/src/msix/PAL/DataCompression/Zlib/CompressionObject.cpp b/src/msix/PAL/DataCompression/Zlib/CompressionObject.cpp index 8d30bd70..b9396d82 100644 --- a/src/msix/PAL/DataCompression/Zlib/CompressionObject.cpp +++ b/src/msix/PAL/DataCompression/Zlib/CompressionObject.cpp @@ -73,11 +73,13 @@ namespace MSIX { { switch (status) { + case Z_BUF_ERROR: + // Since we do not use Z_FINISH, Z_BUF_ERROR just means there is nothing to do. + //__fallthrough; case Z_OK: return CompressionStatus::Ok; case Z_DATA_ERROR: case Z_MEM_ERROR: - case Z_BUF_ERROR: case Z_STREAM_ERROR: case Z_ERRNO: return CompressionStatus::Error; diff --git a/src/msix/UnicodeConversion.cpp b/src/msix/UnicodeConversion.cpp index 9db3ebb6..77811d1a 100644 --- a/src/msix/UnicodeConversion.cpp +++ b/src/msix/UnicodeConversion.cpp @@ -5,6 +5,12 @@ #include #include #include + +#ifdef WIN32 +#include +#include +#endif + #include "UnicodeConversion.hpp" namespace MSIX { @@ -16,8 +22,14 @@ namespace MSIX { std::wstring utf8_to_wstring(const std::string& utf8string) { + #ifdef WIN32 + int size = MultiByteToWideChar(CP_UTF8, 0, utf8string.data(), utf8string.size(), nullptr, 0); + std::wstring result(size, 0); + MultiByteToWideChar(CP_UTF8, 0, utf8string.data(), utf8string.size(), &result[0], size); + #else auto converted = utf8_to_utf16(utf8string); std::wstring result(converted.begin(), converted.end()); + #endif return result; } @@ -30,8 +42,14 @@ namespace MSIX { std::string utf16_to_utf8(const std::wstring& utf16string) { + #ifdef WIN32 + int size = WideCharToMultiByte(CP_UTF8, 0, utf16string.data(), utf16string.size(), nullptr, 0, nullptr, nullptr); + std::string result(size, 0); + WideCharToMultiByte(CP_UTF8, 0, utf16string.data(), utf16string.size(), &result[0], size, nullptr, nullptr); + #else auto converted = std::wstring_convert>{}.to_bytes(utf16string.data()); std::string result(converted.begin(), converted.end()); + #endif return result; } } // namespace MSIX \ No newline at end of file diff --git a/src/msix/ZipObject.cpp b/src/msix/ZipObject.cpp index 37598a9b..39442c11 100644 --- a/src/msix/ZipObject.cpp +++ b/src/msix/ZipObject.cpp @@ -135,22 +135,6 @@ constexpr static const GeneralPurposeBitFlags UnsupportedFlagsMask = GeneralPurposeBitFlags::UNSUPPORTED_14 | GeneralPurposeBitFlags::UNSUPPORTED_15; -////////////////////////////////////////////////////////////////////////////////////////////// -// General Zip validation policies // -////////////////////////////////////////////////////////////////////////////////////////////// -class OffsetOrSize64bit final : public Meta::FieldBase> {}; -class FieldMustBeEmpty final : public Meta::VarLenField>{}; -class VarFieldLenZero final : public Meta::FieldBase> {}; -class InjectedVal2Bytes final : public Meta::FieldBase > {}; -class InjectedVal4Bytes final : public Meta::FieldBase > {}; -class InjectedVal8Bytes final : public Meta::FieldBase > {}; - -class HowCompressed final : public Meta::FieldBase(CompressionType::Deflate), - static_cast(CompressionType::Store)> - > {}; - /* FROM APPNOTE.TXT section 4.5.3: If one of the size or offset fields in the Local or Central directory record is too small to hold the required data, a Zip64 extended information @@ -164,44 +148,38 @@ class HowCompressed final : public Meta::FieldBase> {}; -class Z64ExtInfoHeader final : public Meta::FieldBase(HeaderIDs::Zip64ExtendedInfo)> - > {}; - -class Zip64ExtendedInformation final : public Meta::StructuredObject { public: - void ValidateField(size_t field) override + void Read(const ComPtr& stream) { - ULARGE_INTEGER pos = {0}; - switch (field) - { - case 4: - ThrowErrorIfNot(Error::ZipBadExtendedData, Field<4>().value < m_start.QuadPart, "invalid relative header offset"); - break; - default: - UNEXPECTED; - } - } - - Zip64ExtendedInformation(ULARGE_INTEGER start, IStream* stream) : m_start(start), m_stream(stream) - { - ConfigureField<4>(); + StreamBase::Read(stream, &Field<0>().value); + Meta::ExactValueValidation(Field<0>().value, static_cast(HeaderIDs::Zip64ExtendedInfo)); + + StreamBase::Read(stream, &Field<1>().value); + Meta::OnlyEitherValueValidation(Field<1>().value, 24, 28); + + StreamBase::Read(stream, &Field<2>().value); + + StreamBase::Read(stream, &Field<3>().value); + + StreamBase::Read(stream, &Field<4>().value); + ThrowErrorIfNot(Error::ZipBadExtendedData, Field<4>().value < m_start.QuadPart, "invalid relative header offset"); } + Zip64ExtendedInformation(ULARGE_INTEGER start) : m_start(start) {} + std::uint64_t GetUncompressedSize() noexcept { return Field<2>().value; } void SetUncompressedSize(std::uint64_t v) noexcept { Field<2>().value = v; } std::uint64_t GetCompressedSize() noexcept { return Field<3>().value; } @@ -211,7 +189,6 @@ public: private: ULARGE_INTEGER m_start; - ComPtr m_stream; }; /* TODO: Implement large file support. @@ -236,97 +213,110 @@ answer for now. ////////////////////////////////////////////////////////////////////////////////////////////// // CentralDirectoryFileHeader // ////////////////////////////////////////////////////////////////////////////////////////////// -class CDFH_Header final : public Meta::FieldBase(Signatures::CentralFileHeader)> - > {}; - -class CDFH_DiskNumber final : public Meta::FieldBase> {}; -class CDFH_ExtraField final : public Meta::VarLenField> {}; - -template -class CDFH_GPBitValidation // there are exactly two values that this field is allowed to be -{ -public: - static void Validate(std::size_t, Derived* self) { - ThrowErrorIfNot(Error::ZipCentralDirectoryHeader, - 0 == (self->value & static_cast(UnsupportedFlagsMask)), - "unsupported flag(s) specified"); - } -}; - -class CDFH_GPBit final : public Meta::FieldBase> {}; - -class CentralDirectoryFileHeader final : public Meta::StructuredObject { public: - void ValidateField(size_t field) override + void Read(const ComPtr& stream) { - ULARGE_INTEGER pos = {0}; + StreamBase::Read(stream, &Field<0>().value); + Meta::ExactValueValidation(Field<0>().value, static_cast(Signatures::CentralFileHeader)); - switch(field) + StreamBase::Read(stream, &Field<1>().value); + + StreamBase::Read(stream, &Field<2>().value); + + StreamBase::Read(stream, &Field<3>().value); + ThrowErrorIfNot(Error::ZipCentralDirectoryHeader, + 0 == (Field<3>().value & static_cast(UnsupportedFlagsMask)), + "unsupported flag(s) specified"); + + StreamBase::Read(stream, &Field<4>().value); + Meta::OnlyEitherValueValidation(Field<4>().value, static_cast(CompressionType::Deflate), + static_cast(CompressionType::Store)); + + StreamBase::Read(stream, &Field<5>().value); + StreamBase::Read(stream, &Field<6>().value); + StreamBase::Read(stream, &Field<7>().value); + StreamBase::Read(stream, &Field<8>().value); + StreamBase::Read(stream, &Field<9>().value); + + StreamBase::Read(stream, &Field<10>().value); + ThrowErrorIfNot(Error::ZipCentralDirectoryHeader, (Field<10>().value != 0), "unsupported file name size"); + if (Field<10>().value !=0) {Field<17>().value.resize(Field<10>().value, 0); } + + StreamBase::Read(stream, &Field<11>().value); + if (Field<11>().value != 0) { Field<18>().value.resize(Field<11>().value, 0); } + + StreamBase::Read(stream, &Field<12>().value); + Meta::ExactValueValidation(Field<12>().value, 0); + + StreamBase::Read(stream, &Field<13>().value); + Meta::ExactValueValidation(Field<13>().value, 0); + + StreamBase::Read(stream, &Field<14>().value); + + StreamBase::Read(stream, &Field<15>().value); + StreamBase::Read(stream, &Field<16>().value); + ULARGE_INTEGER pos = {0}; + ThrowHrIfFailed(stream->Seek({0}, StreamBase::Reference::CURRENT, &pos)); + if (!GetIsZip64()) { - case 10: - ThrowErrorIfNot(Error::ZipCentralDirectoryHeader, (Field<10>().value != 0), "unsupported file name size"); - Field<17>().value.resize(Field<10>().value, 0); - break; - case 11: - if (Field<11>().value != 0) { Field<18>().value.resize(Field<11>().value, 0); } - break; - case 16: - ThrowHrIfFailed(m_stream->Seek({0}, StreamBase::Reference::CURRENT, &pos)); - if (!GetIsZip64()) - { ThrowErrorIf(Error::ZipCentralDirectoryHeader, (Field<16>().value >= pos.QuadPart), "invalid relative header offset"); - } - else - { ThrowErrorIf(Error::ZipCentralDirectoryHeader, (Field<16>().value != 0xFFFFFFFF), "invalid zip64 local header offset"); - } - break; - case 18: - // Only process for Zip64ExtendedInformation - if (Field<18>().value.size() > 2 && Field<18>().value[0] == 0x01 && Field<18>().value[1] == 0x00) - { - LARGE_INTEGER zero = {0}; - ThrowHrIfFailed(m_stream->Seek(zero, StreamBase::Reference::CURRENT, &pos)); - auto vectorStream = ComPtr::Make(&Field<18>().value); - m_extendedInfo = std::make_unique(pos, vectorStream.Get()); - ThrowErrorIfNot(Error::ZipCentralDirectoryHeader,(Field<18>().value.size() >= m_extendedInfo->Size()),"Unexpected extended info size"); - m_extendedInfo->Read(vectorStream.Get()); - } - break; - default: - UNEXPECTED; + ThrowErrorIf(Error::ZipCentralDirectoryHeader, (Field<16>().value >= pos.QuadPart), "invalid relative header offset"); + } + else + { + ThrowErrorIf(Error::ZipCentralDirectoryHeader, (Field<16>().value != 0xFFFFFFFF), "invalid zip64 local header offset"); + } + + if (Field<17>().Size()) + { + ThrowHrIfFailed(stream->Read(reinterpret_cast(Field<17>().value.data()), static_cast(Field<17>().Size()), nullptr)); + } + + if (Field<18>().Size()) + { + ThrowHrIfFailed(stream->Read(reinterpret_cast(Field<18>().value.data()), static_cast(Field<18>().Size()), nullptr)); + } + // Only process for Zip64ExtendedInformation + if (Field<18>().Size() > 2 && Field<18>().value[0] == 0x01 && Field<18>().value[1] == 0x00) + { + LARGE_INTEGER zero = {0}; + ThrowHrIfFailed(stream->Seek(zero, StreamBase::Reference::CURRENT, &pos)); + auto vectorStream = ComPtr::Make(&Field<18>().value); + m_extendedInfo = std::make_unique(pos); + ThrowErrorIfNot(Error::ZipCentralDirectoryHeader, (Field<18>().Size() >= m_extendedInfo->Size()), "Unexpected extended info size"); + m_extendedInfo->Read(vectorStream.Get()); + } + + if (Field<19>().Size()) + { + ThrowHrIfFailed(stream->Read(reinterpret_cast(Field<19>().value.data()), static_cast(Field<19>().Size()), nullptr)); } } - CentralDirectoryFileHeader(bool isZip64, IStream* s) : m_isZip64(isZip64), m_stream(s) + CentralDirectoryFileHeader(bool isZip64) : m_isZip64(isZip64) { - ConfigureField<10>(); - ConfigureField<11>(); - ConfigureField<16>(); - ConfigureField<18>(); - SetSignature(static_cast(Signatures::CentralFileHeader)); SetVersionMadeBy(static_cast(ZipVersions::Zip64FormatExtension)); SetVersionNeededToExtract(static_cast(ZipVersions::Zip32DefaultVersion)); // only set to Zip64FormatExtension iff required! @@ -415,86 +405,90 @@ private: void SetExternalFileAttributes(std::uint16_t value) noexcept { Field<15>().value = value; } std::unique_ptr m_extendedInfo; - ComPtr m_stream; bool m_isZip64 = false; };//class CentralDirectoryFileHeader ////////////////////////////////////////////////////////////////////////////////////////////// // LocalFileHeader // ////////////////////////////////////////////////////////////////////////////////////////////// -class LFH_Header final : public Meta::FieldBase(Signatures::LocalFileHeader)> - > {}; - -class LFH_VersionNeeded final : public Meta::FieldBase(ZipVersions::Zip32DefaultVersion), - static_cast(ZipVersions::Zip64FormatExtension)> - > {}; - -class LocalFileHeader final : public Meta::StructuredObject { public: - void ValidateField(size_t field) override + void Read(const ComPtr &stream) { - switch (field) + StreamBase::Read(stream, &Field<0>().value); + Meta::ExactValueValidation( Field<0>().value, static_cast(Signatures::LocalFileHeader)); + + StreamBase::Read(stream, &Field<1>().value); + Meta::OnlyEitherValueValidation(Field<1>().value, static_cast(ZipVersions::Zip32DefaultVersion), + static_cast(ZipVersions::Zip64FormatExtension)); + + StreamBase::Read(stream, &Field<2>().value); + ThrowErrorIfNot(Error::ZipLocalFileHeader, ((Field<2>().value & static_cast(UnsupportedFlagsMask)) == 0), "unsupported flag(s) specified"); + ThrowErrorIfNot(Error::ZipLocalFileHeader, (IsGeneralPurposeBitSet() == m_directoryEntry->IsGeneralPurposeBitSet()), "inconsistent general purpose bits specified"); + + StreamBase::Read(stream, &Field<3>().value); + Meta::OnlyEitherValueValidation(Field<3>().value, static_cast(CompressionType::Deflate), + static_cast(CompressionType::Store)); + + StreamBase::Read(stream, &Field<4>().value); + StreamBase::Read(stream, &Field<5>().value); + StreamBase::Read(stream, &Field<6>().value); + ThrowErrorIfNot(Error::ZipLocalFileHeader, (!IsGeneralPurposeBitSet() || (Field<6>().value == 0)), "Invalid Zip CRC"); + + StreamBase::Read(stream, &Field<7>().value); + ThrowErrorIfNot(Error::ZipLocalFileHeader, (!IsGeneralPurposeBitSet() || (Field<7>().value == 0)), "Invalid Zip compressed size"); + + StreamBase::Read(stream, &Field<8>().value); + + StreamBase::Read(stream, &Field<9>().value); + ThrowErrorIfNot(Error::ZipLocalFileHeader, (Field<9>().value != 0), "unsupported file name size"); + Field<11>().value.resize(GetFileNameLength(), 0); + + StreamBase::Read(stream, &Field<10>().value); + // Even if we don't validate them, we need to read the extra field + if (Field<10>().value != 0) {Field<12>().value.resize(Field<10>().value, 0); } + + if (Field<11>().Size()) { - case 2: - ThrowErrorIfNot(Error::ZipLocalFileHeader, ((Field<2>().value & static_cast(UnsupportedFlagsMask)) == 0), "unsupported flag(s) specified"); - ThrowErrorIfNot(Error::ZipLocalFileHeader, (IsGeneralPurposeBitSet() == m_directoryEntry->IsGeneralPurposeBitSet()), "inconsistent general purpose bits specified"); - break; - case 6: - ThrowErrorIfNot(Error::ZipLocalFileHeader, (!IsGeneralPurposeBitSet() || (Field<6>().value == 0)), "Invalid Zip CRC"); - break; - case 7: - ThrowErrorIfNot(Error::ZipLocalFileHeader, (!IsGeneralPurposeBitSet() || (Field<7>().value == 0)), "Invalid Zip CRC"); - break; - case 9: - ThrowErrorIfNot(Error::ZipLocalFileHeader, (Field<9>().value != 0), "unsupported file name size"); - Field<11>().value.resize(GetFileNameLength(), 0); - break; - case 10: - // Even if we don't validate them, we need to read the extra field - if (Field<10>().value != 0) { Field<12>().value.resize(Field<10>().value,0); } - break; - default: - UNEXPECTED; + ThrowHrIfFailed(stream->Read(reinterpret_cast(Field<11>().value.data()), static_cast(Field<11>().Size()), nullptr)); + } + + if (Field<12>().Size()) + { + ThrowHrIfFailed(stream->Read(reinterpret_cast(Field<12>().value.data()), static_cast(Field<12>().Size()), nullptr)); } } LocalFileHeader(std::shared_ptr directoryEntry) : m_isZip64(directoryEntry->GetIsZip64()), m_directoryEntry(directoryEntry) { - ConfigureField<2>(); - ConfigureField<6>(); - ConfigureField<7>(); - ConfigureField<9>(); - ConfigureField<10>(); } bool IsGeneralPurposeBitSet() noexcept - { return ((GetGeneralPurposeBitFlags() & GeneralPurposeBitFlags::GeneralPurposeBit) == GeneralPurposeBitFlags::GeneralPurposeBit); + { + return ((GetGeneralPurposeBitFlags() & GeneralPurposeBitFlags::GeneralPurposeBit) == GeneralPurposeBitFlags::GeneralPurposeBit); } GeneralPurposeBitFlags GetGeneralPurposeBitFlags() noexcept { return static_cast(Field<2>().value); } CompressionType GetCompressionType() noexcept { return static_cast(Field<3>().value); } std::uint64_t GetCompressedSize() noexcept - { return IsGeneralPurposeBitSet() ? m_directoryEntry->GetCompressedSize() : static_cast(Field<7>().value); + { + return IsGeneralPurposeBitSet() ? m_directoryEntry->GetCompressedSize() : static_cast(Field<7>().value); } std::uint64_t GetUncompressedSize() noexcept @@ -530,62 +524,69 @@ protected: ////////////////////////////////////////////////////////////////////////////////////////////// // Zip64EndOfCentralDirectoryRecord // ////////////////////////////////////////////////////////////////////////////////////////////// -class Z64DiskNumber final : public Meta::FieldBase> {}; -class Z64EOCDRecord final : public Meta::FieldBase(Signatures::Zip64EndOfCD)>> {}; -class Z64EOCDRVersion final : public Meta::FieldBase(ZipVersions::Zip64FormatExtension)>> {}; -class Z64EOCDRCount final : public Meta::FieldBase> {}; - -class Zip64EndOfCentralDirectoryRecord final : public Meta::StructuredObject { public: - void ValidateField(size_t field) override + void Read(const ComPtr& stream) { + StreamBase::Read(stream, &Field<0>().value); + Meta::ExactValueValidation(Field<0>().value, static_cast(Signatures::Zip64EndOfCD)); + + StreamBase::Read(stream, &Field<1>().value); + //4.3.14.1 The value stored into the "size of zip64 end of central + // directory record" should be the size of the remaining + // record and should not include the leading 12 bytes. + ThrowErrorIfNot(Error::Zip64EOCDRecord, (Field<1>().value == (this->Size() - 12)), "invalid size of zip64 EOCD"); + + StreamBase::Read(stream, &Field<2>().value); + Meta::ExactValueValidation(Field<2>().value, static_cast(ZipVersions::Zip64FormatExtension)); + + StreamBase::Read(stream, &Field<3>().value); + Meta::ExactValueValidation(Field<3>().value, static_cast(ZipVersions::Zip64FormatExtension)); + + StreamBase::Read(stream, &Field<4>().value); + Meta::ExactValueValidation(Field<4>().value, 0); + + StreamBase::Read(stream, &Field<5>().value); + Meta::ExactValueValidation(Field<5>().value, 0); + + StreamBase::Read(stream, &Field<6>().value); + Meta::NotValueValidation(Field<6>().value, 0); + + StreamBase::Read(stream, &Field<7>().value); + Meta::NotValueValidation(Field<7>().value, 0); + ThrowErrorIfNot(Error::Zip64EOCDRecord, (Field<7>().value == this->GetTotalNumberOfEntries()), "invalid total number of entries"); + ULARGE_INTEGER pos = {0}; - ThrowHrIfFailed(m_stream->Seek({0}, StreamBase::Reference::CURRENT, &pos)); - - switch (field) + ThrowHrIfFailed(stream->Seek({0}, StreamBase::Reference::CURRENT, &pos)); + StreamBase::Read(stream, &Field<8>().value); + ThrowErrorIfNot(Error::Zip64EOCDRecord, ((Field<8>().value != 0) && (Field<8>().value < pos.QuadPart)), "invalid size of central directory"); + + ThrowHrIfFailed(stream->Seek({0}, StreamBase::Reference::CURRENT, &pos)); + StreamBase::Read(stream, &Field<9>().value); + ThrowErrorIfNot(Error::Zip64EOCDRecord, ((Field<9>().value != 0) && (Field<9>().value < pos.QuadPart)), "invalid size of central directory"); + + if (Field<10>().Size()) { - case 1: - //4.3.14.1 The value stored into the "size of zip64 end of central - // directory record" should be the size of the remaining - // record and should not include the leading 12 bytes. - ThrowErrorIfNot(Error::Zip64EOCDRecord, (Field<1>().value == (this->Size() - 12)), "invalid size of zip64 EOCD"); - break; - case 8: - ThrowErrorIfNot(Error::Zip64EOCDRecord, ((Field<8>().value != 0) && (Field<8>().value < pos.QuadPart)), "invalid size of central directory"); - break; - case 9: - ThrowErrorIfNot(Error::Zip64EOCDRecord, ((Field<9>().value != 0) && (Field<9>().value < pos.QuadPart)), "invalid size of central directory"); - break; - default: - UNEXPECTED; + ThrowHrIfFailed(stream->Read(reinterpret_cast(Field<10>().value.data()), static_cast(Field<10>().Size()), nullptr)); } } - void Validate() + Zip64EndOfCentralDirectoryRecord() { - ThrowErrorIfNot(Error::Zip64EOCDRecord, (Field<7>().value == this->GetTotalNumberOfEntries()), "invalid total number of entries"); - } - - Zip64EndOfCentralDirectoryRecord(const ComPtr& s) : m_stream(s) - { - ConfigureField<1>(); // TODO: can we make this a static value instead? - ConfigureField<8>(); - ConfigureField<9>(); - SetSignature(static_cast(Signatures::Zip64EndOfCD)); SetGetSizeOfZip64CDRecord(this->Size() - 12); SetVersionMadeBy(static_cast(ZipVersions::Zip64FormatExtension)); @@ -614,43 +615,40 @@ private: void SetVersionNeededToExtract(std::uint16_t value) noexcept { Field<3>().value = value; } void SetNumberOfThisDisk(std::uint32_t value) noexcept { Field<4>().value = value; } - ComPtr m_stream; }; //class Zip64EndOfCentralDirectoryRecord ////////////////////////////////////////////////////////////////////////////////////////////// // Zip64EndOfCentralDirectoryLocator // ////////////////////////////////////////////////////////////////////////////////////////////// -class Z64EOCDLocator final : public Meta::FieldBase(Signatures::Zip64EndOfCDLocator)>> {}; -class Z64StartOfDisks final : public Meta::FieldBase> {}; -class Z64NumberOfDisks final : public Meta::FieldBase> {}; - -class Zip64EndOfCentralDirectoryLocator final : public Meta::StructuredObject { public: - void ValidateField(size_t field) override + void Read(const ComPtr& stream) { - ULARGE_INTEGER pos = {0}; - switch (field) - { - case 2: - ThrowHrIfFailed(m_stream->Seek({0}, StreamBase::Reference::CURRENT, &pos)); - ThrowErrorIfNot(Error::Zip64EOCDLocator, ((Field<2>().value != 0) && (Field<2>().value < pos.QuadPart)), "Invalid relative offset"); - break; - default: - UNEXPECTED; - } + StreamBase::Read(stream, &Field<0>().value); + Meta::ExactValueValidation(Field<0>().value, static_cast(Signatures::Zip64EndOfCDLocator)); + + StreamBase::Read(stream, &Field<1>().value); + Meta::ExactValueValidation(Field<1>().value, 0); + + ULARGE_INTEGER pos = {0}; + StreamBase::Read(stream, &Field<2>().value); + ThrowHrIfFailed(stream->Seek({0}, StreamBase::Reference::CURRENT, &pos)); + ThrowErrorIfNot(Error::Zip64EOCDLocator, ((Field<2>().value != 0) && (Field<2>().value < pos.QuadPart)), "Invalid relative offset"); + + StreamBase::Read(stream, &Field<3>().value); + Meta::ExactValueValidation(Field<3>().value, 1); } - Zip64EndOfCentralDirectoryLocator(const ComPtr& s) : m_stream(s) + Zip64EndOfCentralDirectoryLocator() { - ConfigureField<2>(); // set smart defaults. SetSignature(static_cast(Signatures::Zip64EndOfCDLocator)); SetNumberOfDisk(0); @@ -664,20 +662,15 @@ private: void SetSignature(std::uint32_t value) noexcept { Field<0>().value = value; } void SetNumberOfDisk(std::uint32_t value) noexcept { Field<1>().value = value; } void SetTotalNumberOfDisks(std::uint32_t value) noexcept { Field<3>().value = value; } - - ComPtr m_stream; }; //class Zip64EndOfCentralDirectoryLocator ////////////////////////////////////////////////////////////////////////////////////////////// // EndOfCentralDirectoryRecord // ////////////////////////////////////////////////////////////////////////////////////////////// -class EOCDSignature final : public Meta::FieldBase(Signatures::EndOfCentralDirectory)>> {}; -class EOCDNumberDisks final : public Meta::FieldBase> {}; - -class EndCentralDirectoryRecord final : public Meta::StructuredObject { public: - void Validate() + void Read(const ComPtr& stream) { - ThrowErrorIf(Error::ZipEOCDRecord, (Field<1>().value != Field<2>().value), "field missmatch"); - ThrowErrorIf(Error::ZipEOCDRecord, (Field<3>().value != Field<4>().value), "field missmatch"); + StreamBase::Read(stream, &Field<0>().value); + Meta::ExactValueValidation(Field<0>().value, static_cast(Signatures::EndOfCentralDirectory)); + StreamBase::Read(stream, &Field<1>().value); + Meta::OnlyEitherValueValidation(Field<1>().value, 0, 0xFFFF); + + StreamBase::Read(stream, &Field<2>().value); + Meta::OnlyEitherValueValidation(Field<2>().value, 0, 0xFFFF); + ThrowErrorIf(Error::ZipEOCDRecord, (Field<1>().value != Field<2>().value), "field missmatch"); m_isZip64 = (0xFFFF == Field<2>().value); + + StreamBase::Read(stream, &Field<3>().value); if (Field<3>().value != 0 && Field<3>().value != 0xFFFF) { m_archiveHasZip64Locator = false; } + + StreamBase::Read(stream, &Field<4>().value); + ThrowErrorIf(Error::ZipEOCDRecord, (Field<3>().value != Field<4>().value), "field missmatch"); + + StreamBase::Read(stream, &Field<5>().value); + StreamBase::Read(stream, &Field<6>().value); + if(m_archiveHasZip64Locator) { ThrowErrorIf(Error::ZipEOCDRecord, ((Field<5>().value != 0) && (Field<5>().value != 0xFFFFFFFF)), @@ -707,8 +715,16 @@ public: ThrowErrorIf(Error::ZipEOCDRecord, ((Field<6>().value != 0) && (Field<6>().value != 0xFFFFFFFF)), "unsupported offset of start of central directory"); } + + StreamBase::Read(stream, &Field<7>().value); + Meta::ExactValueValidation(Field<7>().value, 0); + + if (Field<8>().Size()) + { + ThrowHrIfFailed(stream->Read(reinterpret_cast(Field<8>().value.data()), static_cast(Field<8>().Size()), nullptr)); + } } - + EndCentralDirectoryRecord() { SetSignature(static_cast(Signatures::EndOfCentralDirectory)); @@ -731,7 +747,7 @@ public: private: bool m_isZip64 = false; bool m_archiveHasZip64Locator = true; - + void SetSignature(std::uint32_t value) noexcept { Field<0>().value = value; } void SetNumberOfDisk(std::uint16_t value) noexcept { Field<1>().value = value; } void SetDiskStart(std::uint16_t value) noexcept { Field<2>().value = value; } @@ -745,7 +761,7 @@ private: ////////////////////////////////////////////////////////////////////////////////////////////// // ZipObject member implementation // -////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////// std::vector ZipObject::GetFileNames(FileNameOptions) { std::vector result; @@ -782,7 +798,7 @@ ZipObject::ZipObject(IMsixFactory* appxFactory, const ComPtr& stream) : // find where the zip central directory exists. std::uint64_t offsetStartOfCD = 0; std::uint64_t totalNumberOfEntries = 0; - Zip64EndOfCentralDirectoryLocator zip64Locator(m_stream.Get()); + Zip64EndOfCentralDirectoryLocator zip64Locator; if (!endCentralDirectoryRecord.GetArchiveHasZip64Locator()) { offsetStartOfCD = endCentralDirectoryRecord.GetStartOfCentralDirectory(); @@ -795,7 +811,7 @@ ZipObject::ZipObject(IMsixFactory* appxFactory, const ComPtr& stream) : zip64Locator.Read(m_stream.Get()); // now read the end of zip central directory record - Zip64EndOfCentralDirectoryRecord zip64EndOfCentralDirectory(m_stream); + Zip64EndOfCentralDirectoryRecord zip64EndOfCentralDirectory; pos.QuadPart = zip64Locator.GetRelativeOffset(); ThrowHrIfFailed(m_stream->Seek(pos, StreamBase::Reference::START, nullptr)); zip64EndOfCentralDirectory.Read(m_stream.Get()); @@ -809,7 +825,7 @@ ZipObject::ZipObject(IMsixFactory* appxFactory, const ComPtr& stream) : ThrowHrIfFailed(m_stream->Seek(pos, StreamBase::Reference::START, nullptr)); for (std::uint32_t index = 0; index < totalNumberOfEntries; index++) { - auto centralFileHeader = std::make_shared(endCentralDirectoryRecord.GetIsZip64(), m_stream.Get()); + auto centralFileHeader = std::make_shared(endCentralDirectoryRecord.GetIsZip64()); centralFileHeader->Read(m_stream.Get()); // TODO: ensure that there are no collisions on name! centralDirectory.insert(std::make_pair(centralFileHeader->GetFileName(), centralFileHeader)); diff --git a/src/msix/msix.cpp b/src/msix/msix.cpp index 6a743bcd..00c100eb 100644 --- a/src/msix/msix.cpp +++ b/src/msix/msix.cpp @@ -185,7 +185,7 @@ MSIX_API HRESULT STDMETHODCALLTYPE CreateStreamOnFileUTF16( IStream** stream) noexcept try { MSIX::FileStream::Mode mode = forRead ? MSIX::FileStream::Mode::READ : MSIX::FileStream::Mode::WRITE_UPDATE; - *stream = MSIX::ComPtr::Make(MSIX::utf16_to_utf8(utf16File), mode).Detach(); + *stream = MSIX::ComPtr::Make(utf16File, mode).Detach(); return static_cast(MSIX::Error::OK); } CATCH_RETURN(); diff --git a/test/MacOS-Linux/MacOS-Linux-Etc.sh b/test/MacOS-Linux/MacOS-Linux-Etc.sh index fd0e4f4a..5d312b78 100755 --- a/test/MacOS-Linux/MacOS-Linux-Etc.sh +++ b/test/MacOS-Linux/MacOS-Linux-Etc.sh @@ -72,6 +72,7 @@ FindBinFolder RunTest 2 ./../appx/Empty.appx -sv RunTest 0 ./../appx/HelloWorld.appx -ss +RunTest 0 ./../appx/NotepadPlusPlus.appx -ss RunTest 66 ./../appx/SignatureNotLastPart-ERROR_BAD_FORMAT.appx RunTest 66 ./../appx/SignedTamperedBlockMap-TRUST_E_BAD_DIGEST.appx RunTest 65 ./../appx/SignedTamperedBlockMap-TRUST_E_BAD_DIGEST.appx -sv @@ -138,6 +139,8 @@ ValidateResult ExpectedResult/$directory/FlatBundleWithAsset.txt CleanupUnpackFolder +RunTest 0 ./../appx/महसुस/StoreSigned_Desktop_x64_MoviesTV.appx + RunTest 0 ./../appx/StoreSigned_Desktop_x64_MoviesTV.appx ValidateResult ExpectedResult/$directory/StoreSigned_Desktop_x64_MoviesTV.txt diff --git a/test/Win32/Win32.ps1 b/test/Win32/Win32.ps1 index 6a1e2b6b..ae0cc452 100644 --- a/test/Win32/Win32.ps1 +++ b/test/Win32/Win32.ps1 @@ -88,6 +88,7 @@ FindBinFolder # Normal package RunTest 0x8bad0002 .\..\appx\Empty.appx "-sv" RunTest 0x00000000 .\..\appx\HelloWorld.appx "-ss" +RunTest 0x00000000 .\..\appx\NotepadPlusPlus.appx "-ss" RunTest 0x8bad0042 .\..\appx\SignatureNotLastPart-ERROR_BAD_FORMAT.appx # RunTest 0x134 .\appx\SignedMismatchedPublisherName-ERROR_BAD_FORMAT.appx RunTest 0x8bad0042 .\..\appx\SignedTamperedBlockMap-TRUST_E_BAD_DIGEST.appx diff --git a/test/api/ApiTest.hpp b/test/api/ApiTest.hpp index 8c2f6eab..d1a0adef 100644 --- a/test/api/ApiTest.hpp +++ b/test/api/ApiTest.hpp @@ -32,7 +32,7 @@ public: m_line(line) { m_actual = std::to_string(static_cast(actual)); - m_expected = std::to_string(static_cast(actual)); + m_expected = std::to_string(static_cast(expected)); } std::string& Actual() { return m_actual; } diff --git a/test/appx/NotepadPlusPlus.appx b/test/appx/NotepadPlusPlus.appx new file mode 100644 index 00000000..83b2ae53 Binary files /dev/null and b/test/appx/NotepadPlusPlus.appx differ diff --git a/test/appx/महसुस/StoreSigned_Desktop_x64_MoviesTV.appx b/test/appx/महसुस/StoreSigned_Desktop_x64_MoviesTV.appx new file mode 100644 index 00000000..239876cc Binary files /dev/null and b/test/appx/महसुस/StoreSigned_Desktop_x64_MoviesTV.appx differ diff --git a/test/mobile/AndroidBVT/app/src/main/cpp/native-lib.cpp b/test/mobile/AndroidBVT/app/src/main/cpp/native-lib.cpp index ec239f2a..475bb86e 100644 --- a/test/mobile/AndroidBVT/app/src/main/cpp/native-lib.cpp +++ b/test/mobile/AndroidBVT/app/src/main/cpp/native-lib.cpp @@ -80,6 +80,7 @@ Java_com_microsoft_androidbvt_MainActivity_RunTests(JNIEnv* env, jobject /* this CopyFilesFromAssets(env, assetManager, filePath, "BlockMap"); CopyFilesFromAssets(env, assetManager, filePath, "bundles"); CopyFilesFromAssets(env, assetManager, filePath, "flat"); + CopyFilesFromAssets(env, assetManager, filePath, "महसुस"); signed long hr = RunTests(const_cast(filePath.c_str()), const_cast(filePath.c_str())); if(hr == 0) { diff --git a/test/mobile/common/MobileTests.cpp b/test/mobile/common/MobileTests.cpp index 1e6a7e80..1b2b7281 100644 --- a/test/mobile/common/MobileTests.cpp +++ b/test/mobile/common/MobileTests.cpp @@ -117,6 +117,7 @@ static HRESULT RunTestsInternal(std::string source, std::string target) hr = RunTest(source + "Empty.appx", unpackFolder, sv, 2); hr = RunTest(source + "HelloWorld.appx", unpackFolder, ss, 0); + hr = RunTest(source + "NotepadPlusPlus.appx", unpackFolder, ss, 0); hr = RunTest(source + "SignatureNotLastPart-ERROR_BAD_FORMAT.appx", unpackFolder, full, 66); hr = RunTest(source + "SignedTamperedBlockMap-TRUST_E_BAD_DIGEST.appx", unpackFolder, full, 66); hr = RunTest(source + "SignedTamperedBlockMap-TRUST_E_BAD_DIGEST.appx", unpackFolder, sv, 65); @@ -125,6 +126,7 @@ static HRESULT RunTestsInternal(std::string source, std::string target) hr = RunTest(source + "SignedTamperedContentTypes-TRUST_E_BAD_DIGEST.appx", unpackFolder, full, 66); hr = RunTest(source + "SignedUntrustedCert-CERT_E_CHAINING.appx", unpackFolder, full, 66); hr = RunTest(source + "StoreSigned_Desktop_x64_MoviesTV.appx", unpackFolder, full, 0); + hr = RunTest(source + "महसुस/StoreSigned_Desktop_x64_MoviesTV.appx", unpackFolder, full, 0); hr = RunTest(source + "TestAppxPackage_Win32.appx", unpackFolder, ss, 0); hr = RunTest(source + "TestAppxPackage_x64.appx", unpackFolder, ss, 0); hr = RunTest(source + "UnsignedZip64WithCI-APPX_E_MISSING_REQUIRED_FILE.appx", unpackFolder, full, 18); diff --git a/test/mobile/iOSBVT/iOSBVT.xcodeproj/project.pbxproj b/test/mobile/iOSBVT/iOSBVT.xcodeproj/project.pbxproj index b3c9b5b7..f97eef48 100644 --- a/test/mobile/iOSBVT/iOSBVT.xcodeproj/project.pbxproj +++ b/test/mobile/iOSBVT/iOSBVT.xcodeproj/project.pbxproj @@ -1,4 +1,4 @@ -// !$*UTF8*$! +// !$*UTF8*$! { archiveVersion = 1; classes = { @@ -38,6 +38,8 @@ 4C7F378720783FD2002942F4 /* StoreSigned_Desktop_x86_x64_MoviesTV.appxbundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7F376C20783FC2002942F4 /* StoreSigned_Desktop_x86_x64_MoviesTV.appxbundle */; }; 4C7F3789207848EC002942F4 /* libmsixtestcommon.0.0.0.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7F3788207848EC002942F4 /* libmsixtestcommon.0.0.0.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; 4C7F378B20784901002942F4 /* libmsix.0.0.0.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C7F378A20784901002942F4 /* libmsix.0.0.0.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; + 4C80CD9E216EE2B7008E3292 /* StoreSigned_Desktop_x64_MoviesTV.appx in Resources */ = {isa = PBXBuildFile; fileRef = 4C80CD9D216EE2B7008E3292 /* StoreSigned_Desktop_x64_MoviesTV.appx */; }; + 4C80CDA0216EE32A008E3292 /* StoreSigned_Desktop_x64_MoviesTV.appx in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4C80CD9D216EE2B7008E3292 /* StoreSigned_Desktop_x64_MoviesTV.appx */; }; 4CAC1C2E2135DCC0005C3B2C /* assets.appx in Resources */ = {isa = PBXBuildFile; fileRef = 4CAC1C1A2135DCC0005C3B2C /* assets.appx */; }; 4CAC1C2F2135DCC0005C3B2C /* FlatBundleWithAsset.appxbundle in Resources */ = {isa = PBXBuildFile; fileRef = 4CAC1C1B2135DCC0005C3B2C /* FlatBundleWithAsset.appxbundle */; }; 4CAC1C302135DCC0005C3B2C /* language-de.appx in Resources */ = {isa = PBXBuildFile; fileRef = 4CAC1C1C2135DCC0005C3B2C /* language-de.appx */; }; @@ -78,6 +80,7 @@ 4CAC1C532135DCDA005C3B2C /* scale-140.appx in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4CAC1C2B2135DCC0005C3B2C /* scale-140.appx */; }; 4CAC1C542135DCDA005C3B2C /* scale-180.appx in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4CAC1C2C2135DCC0005C3B2C /* scale-180.appx */; }; 4CAC1C552135DCDA005C3B2C /* scale-240.appx in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4CAC1C2D2135DCC0005C3B2C /* scale-240.appx */; }; + 6A0FC3D72179413E003B606A /* NotepadPlusPlus.appx in Resources */ = {isa = PBXBuildFile; fileRef = 6A0FC3D62179413E003B606A /* NotepadPlusPlus.appx */; }; EEE4055020225CDF007B25CE /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = EEE4054F20225CDF007B25CE /* AppDelegate.m */; }; EEE4055320225CDF007B25CE /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = EEE4055220225CDF007B25CE /* ViewController.m */; }; EEE4055620225CDF007B25CE /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = EEE4055420225CDF007B25CE /* Main.storyboard */; }; @@ -189,6 +192,16 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 4C80CD9F216EE301008E3292 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "महसुस"; + dstSubfolderSpec = 7; + files = ( + 4C80CDA0216EE32A008E3292 /* StoreSigned_Desktop_x64_MoviesTV.appx in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 4CAC1C182135DC9A005C3B2C /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -307,6 +320,7 @@ 4C7F376C20783FC2002942F4 /* StoreSigned_Desktop_x86_x64_MoviesTV.appxbundle */ = {isa = PBXFileReference; lastKnownFileType = file; path = StoreSigned_Desktop_x86_x64_MoviesTV.appxbundle; sourceTree = ""; }; 4C7F3788207848EC002942F4 /* libmsixtestcommon.0.0.0.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libmsixtestcommon.0.0.0.dylib; path = ../../../.vs/lib/libmsixtestcommon.0.0.0.dylib; sourceTree = ""; }; 4C7F378A20784901002942F4 /* libmsix.0.0.0.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libmsix.0.0.0.dylib; path = ../../../.vs/lib/libmsix.0.0.0.dylib; sourceTree = ""; }; + 4C80CD9D216EE2B7008E3292 /* StoreSigned_Desktop_x64_MoviesTV.appx */ = {isa = PBXFileReference; lastKnownFileType = file; path = StoreSigned_Desktop_x64_MoviesTV.appx; sourceTree = ""; }; 4CAC1C1A2135DCC0005C3B2C /* assets.appx */ = {isa = PBXFileReference; lastKnownFileType = file; path = assets.appx; sourceTree = ""; }; 4CAC1C1B2135DCC0005C3B2C /* FlatBundleWithAsset.appxbundle */ = {isa = PBXFileReference; lastKnownFileType = file; path = FlatBundleWithAsset.appxbundle; sourceTree = ""; }; 4CAC1C1C2135DCC0005C3B2C /* language-de.appx */ = {isa = PBXFileReference; lastKnownFileType = file; path = "language-de.appx"; sourceTree = ""; }; @@ -327,6 +341,7 @@ 4CAC1C2B2135DCC0005C3B2C /* scale-140.appx */ = {isa = PBXFileReference; lastKnownFileType = file; path = "scale-140.appx"; sourceTree = ""; }; 4CAC1C2C2135DCC0005C3B2C /* scale-180.appx */ = {isa = PBXFileReference; lastKnownFileType = file; path = "scale-180.appx"; sourceTree = ""; }; 4CAC1C2D2135DCC0005C3B2C /* scale-240.appx */ = {isa = PBXFileReference; lastKnownFileType = file; path = "scale-240.appx"; sourceTree = ""; }; + 6A0FC3D62179413E003B606A /* NotepadPlusPlus.appx */ = {isa = PBXFileReference; lastKnownFileType = file; path = NotepadPlusPlus.appx; sourceTree = ""; }; EEE4054B20225CDF007B25CE /* iOSBVT.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iOSBVT.app; sourceTree = BUILT_PRODUCTS_DIR; }; EEE4054E20225CDF007B25CE /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; EEE4054F20225CDF007B25CE /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; @@ -424,6 +439,14 @@ path = ../../appx/bundles; sourceTree = ""; }; + 4C80CD9C216EE2B7008E3292 /* महसुस */ = { + isa = PBXGroup; + children = ( + 4C80CD9D216EE2B7008E3292 /* StoreSigned_Desktop_x64_MoviesTV.appx */, + ); + path = "महसुस"; + sourceTree = ""; + }; 4CAC1C192135DCC0005C3B2C /* flat */ = { isa = PBXGroup; children = ( @@ -494,10 +517,12 @@ EEE4056B20225EF5007B25CE /* appx */ = { isa = PBXGroup; children = ( + 4C80CD9C216EE2B7008E3292 /* महसुस */, EEE4056C20225EF5007B25CE /* BlockMap */, EEE4057720225EF5007B25CE /* CentennialCoffee.appx */, EEE4057820225EF5007B25CE /* Empty.appx */, EEE4057920225EF5007B25CE /* HelloWorld.appx */, + 6A0FC3D62179413E003B606A /* NotepadPlusPlus.appx */, EEE4057A20225EF5007B25CE /* InvalidSignatureBadCodeIntegrity.appx */, EEE4057B20225EF5007B25CE /* InvalidSignatureInvalidCodeIntegrityXML.appx */, EEE4057C20225EF5007B25CE /* OPC_E_ZIP_CORRUPTED_ARCHIVE.appx */, @@ -550,6 +575,7 @@ 4C11C9CB2048C60500F6BE01 /* CopyFiles */, 4C7F375020783F90002942F4 /* CopyFiles */, 4CAC1C182135DC9A005C3B2C /* CopyFiles */, + 4C80CD9F216EE301008E3292 /* CopyFiles */, ); buildRules = ( ); @@ -602,7 +628,9 @@ EEE4059620225EF5007B25CE /* InvalidSignatureInvalidCodeIntegrityXML.appx in Resources */, 4CAC1C352135DCC0005C3B2C /* language-ja.appx in Resources */, EEE4059020225EF5007B25CE /* No_blockmap.appx in Resources */, + 6A0FC3D72179413E003B606A /* NotepadPlusPlus.appx in Resources */, EEE4058D20225EF5007B25CE /* HelloWorld.appx in Resources */, + 4C80CD9E216EE2B7008E3292 /* StoreSigned_Desktop_x64_MoviesTV.appx in Resources */, EEE4059720225EF5007B25CE /* OPC_E_ZIP_CORRUPTED_ARCHIVE.appx in Resources */, 4CAC1C2E2135DCC0005C3B2C /* assets.appx in Resources */, EEE4059420225EF5007B25CE /* HelloWorld.appx in Resources */,