mirror of
https://github.com/modernw/App-Installer-For-Windows-8.x-Reset.git
synced 2026-04-11 17:57:19 +10:00
2026 lines
68 KiB
C++
2026 lines
68 KiB
C++
// 下列 ifdef 块是创建使从 DLL 导出更简单的
|
||
// 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 PKGREAD_EXPORTS
|
||
// 符号编译的。在使用此 DLL 的
|
||
// 任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将
|
||
// PKGREAD_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的
|
||
// 符号视为是被导出的。
|
||
#ifndef _APPX_PACKAGE_READER_H_
|
||
#define _APPX_PACKAGE_READER_H_
|
||
#ifdef PKGREAD_EXPORTS
|
||
#define PKGREAD_API __declspec(dllexport)
|
||
#else
|
||
#define PKGREAD_API __declspec(dllimport)
|
||
#endif
|
||
|
||
#ifdef __cplusplus
|
||
#define _DEFAULT_INIT_VALUE_(_init_value_) = _init_value_
|
||
#ifndef PKGREAD_EXPORTS
|
||
#define _DEFAULT_INIT_VALUE_FORFUNC_(_init_value_) = _init_value_
|
||
#else
|
||
#define _DEFAULT_INIT_VALUE_FORFUNC_(_init_value_)
|
||
#endif
|
||
#else
|
||
#define _DEFAULT_INIT_VALUE_(_init_value_)
|
||
#define _DEFAULT_INIT_VALUE_FORFUNC_(_init_value_)
|
||
#endif
|
||
|
||
#if defined (__cplusplus) && defined (PKGREAD_EXPORTS)
|
||
#include <iostream>
|
||
#endif
|
||
|
||
#ifndef _TYPE_STRUCT_VERSION_
|
||
#define _TYPE_STRUCT_VERSION_
|
||
typedef struct _VERSION
|
||
{
|
||
UINT16 major _DEFAULT_INIT_VALUE_ (0),
|
||
minor _DEFAULT_INIT_VALUE_ (0),
|
||
build _DEFAULT_INIT_VALUE_ (0),
|
||
revision _DEFAULT_INIT_VALUE_ (0);
|
||
#if defined (__cplusplus) && defined (PKGREAD_EXPORTS)
|
||
_VERSION (UINT16 major = 0, UINT16 minor = 0, UINT16 build = 0, UINT16 revision = 0):
|
||
major (major), minor (minor), build (build), revision (revision) {}
|
||
friend std::ostream &operator << (std::ostream &o, const _VERSION &v)
|
||
{
|
||
return o << v.major << "." << v.minor << "." << v.build << "." << v.revision;
|
||
}
|
||
friend std::wostream &operator << (std::wostream &o, const _VERSION &v)
|
||
{
|
||
return o << v.major << L"." << v.minor << L"." << v.build << L"." << v.revision;
|
||
}
|
||
#endif
|
||
} VERSION;
|
||
#endif
|
||
|
||
#ifdef __cplusplus
|
||
extern "C"
|
||
{
|
||
#endif
|
||
|
||
#ifndef _TYPE_STRUCT_LIST_PVOID_
|
||
#define _TYPE_STRUCT_LIST_PVOID_
|
||
typedef struct _LIST_PVOID
|
||
{
|
||
DWORD dwSize _DEFAULT_INIT_VALUE_ (0);
|
||
LPVOID alpVoid [1] _DEFAULT_INIT_VALUE_ ({NULL});
|
||
} LIST_PVOID, *HLIST_PVOID;
|
||
#endif
|
||
|
||
#ifndef _TYPE_STRUCT_PAIR_PVOID_
|
||
#define _TYPE_STRUCT_PAIR_PVOID_
|
||
typedef struct _PAIR_PVOID_
|
||
{
|
||
LPVOID lpKey _DEFAULT_INIT_VALUE_ (NULL);
|
||
LPVOID lpValue _DEFAULT_INIT_VALUE_ (NULL);
|
||
} PAIR_PVOID, *HPAIR_PVOID;
|
||
#endif
|
||
|
||
#define TEMPLATE_STRUCT(_typename_) typedef struct _typename_##__ _typename_
|
||
TEMPLATE_STRUCT (PKGREADER);
|
||
typedef PKGREADER *HPKGREAD;
|
||
TEMPLATE_STRUCT (APPENUMERATOR);
|
||
typedef APPENUMERATOR *HAPPENUMERATOR;
|
||
|
||
#define PKGTYPE_UNKNOWN 0
|
||
#define PKGTYPE_APPX 1
|
||
#define PKGTYPE_BUNDLE 2
|
||
#define PKGROLE_UNKNOWN 0
|
||
#define PKGROLE_APPLICATION 1
|
||
#define PKGROLE_FRAMEWORK 2
|
||
#define PKGROLE_RESOURCE 3
|
||
// 创建包读取器
|
||
PKGREAD_API HPKGREAD CreatePackageReader ();
|
||
// 通过包读取器打开包
|
||
PKGREAD_API BOOL LoadPackageFromFile (_In_ HPKGREAD hReader, _In_ LPCWSTR lpFilePath);
|
||
// 销毁包读取器(必须)
|
||
PKGREAD_API void DestroyPackageReader (_In_ HPKGREAD hReader);
|
||
// 获取包的类型:Appx 包还是 AppxBundle 包。返回 PKGTYPE_* 宏
|
||
PKGREAD_API WORD GetPackageType (_In_ HPKGREAD hReader);
|
||
// 返回包是否有效。无效的包会返回假。
|
||
PKGREAD_API BOOL IsPackageValid (_In_ HPKGREAD hReader);
|
||
// 获取包的类型:是应用包、框架包还是资源包。
|
||
// 对于 AppxBundle 包永远返回是资源包(因为框架包无法打包成 AppxBundle,资源包必须与应用包一同打包进 AppxBundle)。
|
||
// 返回 PKGROLE_* 宏。
|
||
PKGREAD_API WORD GetPackageRole (_In_ HPKGREAD hReader);
|
||
|
||
// Identity
|
||
// 对于 AppxBundle 包来说,AppxBundle 包与储存的 Appx 的包的身份信息并不一致(不一致在版本号和处理器架构上)
|
||
#define PKG_IDENTITY_BUNDLE_GETAPPXINFO ((PKGTYPE_BUNDLE && 0xFFFF) << 16)
|
||
#define PKG_IDENTITY_NAME 0
|
||
#define PKG_IDENTITY_PUBLISHER 1
|
||
#define PKG_IDENTITY_PACKAGEFAMILYNAME 2
|
||
#define PKG_IDENTITY_PACKAGEFULLNAME 3
|
||
#define PKG_IDENTITY_RESOURCEID 4
|
||
#define PKG_ARCHITECTURE_UNKNOWN 0x0
|
||
#define PKG_ARCHITECTURE_X86 0x1
|
||
#define PKG_ARCHITECTURE_X64 0x2
|
||
#define PKG_ARCHITECTURE_ARM 0x4
|
||
#define PKG_ARCHITECTURE_ARM64 0x8
|
||
#define PKG_ARCHITECTURE_NEUTRAL 0xF
|
||
// 获取身份信息能获取文本值的项。支持 PKG_IDENTITY_* 前缀的宏 NAME, PUBLISHER, PACKAGEFAMILYNAME, PACKAGEFULLNAME, RESOURCEID。
|
||
// 当与 PKG_IDENTITY_BUNDLE_GETAPPXINFO 通过位或结合时,则获取 AppxBundle 中某一个应用包。
|
||
PKGREAD_API LPWSTR GetPackageIdentityStringValue (_In_ HPKGREAD hReader, _In_ DWORD dwName);
|
||
#define GetPackageIdentityName(_In_hReader_) GetPackageIdentityStringValue (_In_hReader_, PKG_IDENTITY_NAME)
|
||
#define GetPackageIdentityPublisher(_In_hReader_) GetPackageIdentityStringValue (_In_hReader_, PKG_IDENTITY_PUBLISHER)
|
||
#define GetPackageIdentityPackageFamilyName(_In_hReader_) GetPackageIdentityStringValue (_In_hReader_, PKG_IDENTITY_PACKAGEFAMILYNAME)
|
||
#define GetPackageIdentityPackageFullName(_In_hReader_) GetPackageIdentityStringValue (_In_hReader_, PKG_IDENTITY_PACKAGEFULLNAME)
|
||
#define GetPackageIdentityResourceId(_In_hReader_) GetPackageIdentityStringValue (_In_hReader_, PKG_IDENTITY_RESOURCEID)
|
||
// 获取身份信息。当 bGetSubPkgVer 为真,且打开的包为 AppxBundle 包,返回 AppxBundle 包中的某个应用包的版本号。
|
||
PKGREAD_API BOOL GetPackageIdentityVersion (_In_ HPKGREAD hReader, _Out_ VERSION *pVersion, _In_ BOOL bGetSubPkgVer _DEFAULT_INIT_VALUE_FORFUNC_ (0));
|
||
// 对于 AppxBundle 包,当传入的值有 PKG_IDENTITY_BUNDLE_GETAPPXINFO,则返回一个按位值,如 0b0011,则意味着支持 x86 和 x64
|
||
PKGREAD_API BOOL GetPackageIdentityArchitecture (_In_ HPKGREAD hReader, _Out_ DWORD *pdwArchi);
|
||
|
||
// Properties
|
||
// 获取字符串值
|
||
#define PKG_PROPERTIES_DISPLAYNAME L"DisplayName"
|
||
#define PKG_PROPERTIES_DESCRIPTION L"Description"
|
||
#define PKG_PROPERTIES_LOGO L"Logo"
|
||
#define PKG_PROPERTIES_PUBLISHER L"PublisherDisplayName"
|
||
// 获取逻辑型值
|
||
#define PKG_PROPERTIES_FRAMEWORD L"Framework"
|
||
#define PKG_PROPERTIES_IS_RESOURCE L"ResourcePackage"
|
||
// 传入参数参考:https://learn.microsoft.com/en-us/windows/win32/api/appxpackaging/nf-appxpackaging-iappxmanifestproperties-getstringvalue
|
||
// 可以使用宏 PKG_PROPERTIES_* 前缀的 DISPLAYNAME, DESCRIPTION, LOGO, PUBLISHER
|
||
PKGREAD_API LPWSTR GetPackagePropertiesStringValue (_In_ HPKGREAD hReader, _In_ LPCWSTR lpName);
|
||
#define GetPackagePropertiesDisplayName(_In_hReader_) GetPackagePropertiesStringValue (_In_hReader_, PKG_PROPERTIES_DISPLAYNAME)
|
||
#define GetPackagePropertiesDescription(_In_hReader_) GetPackagePropertiesStringValue (_In_hReader_, PKG_PROPERTIES_DESCRIPTION)
|
||
#define GetPackagePropertiesLogo(_In_hReader_) GetPackagePropertiesStringValue (_In_hReader_, PKG_PROPERTIES_LOGO)
|
||
#define GetPackagePropertiesPublisher(_In_hReader_) GetPackagePropertiesStringValue (_In_hReader_, PKG_PROPERTIES_PUBLISHER)
|
||
// 传入参数参考:https://learn.microsoft.com/zh-cn/windows/win32/api/appxpackaging/nf-appxpackaging-iappxmanifestproperties-getboolvalue
|
||
// 可以使用宏 PKG_PROPERTIES_* 前缀的 FRAMEWORD, IS_RESOURCE (Windows 8.1 支持)
|
||
PKGREAD_API HRESULT GetPackagePropertiesBoolValue (_In_ HPKGREAD hReader, _In_ LPCWSTR lpName, _Outptr_ BOOL *pRet);
|
||
#define GetPackagePropertiesIsFramework(_In_hReader_, _Outptr_pRetValue_) GetPackagePropertiesBoolValue (_In_hReader_, PKG_PROPERTIES_FRAMEWORD, _Outptr_pRetValue_)
|
||
#define GetPackagePropertiesIsResourcePackage(_In_hReader_, _Outptr_pRetValue_) GetPackagePropertiesBoolValue (_In_hReader_, PKG_PROPERTIES_IS_RESOURCE, _Outptr_pRetValue_)
|
||
// Applications
|
||
// 注意:由于读取 Application 在官方 API 中是枚举类型,只能枚举一次。
|
||
// 所以请预先安排好需要的信息,并在枚举时进行缓存。
|
||
// 添加和删除的请参考这些:https://learn.microsoft.com/en-us/windows/win32/api/appxpackaging/nf-appxpackaging-iappxmanifestapplication-getstringvalue
|
||
// DLL 本身支持:Id, DisplayName, BackgroundColor, ForegroundText, ShortName, Square44x44Logo
|
||
// 注:一定会保留项:AppUserModelID。这是必须项。
|
||
PKGREAD_API BOOL AddPackageApplicationItemGetName (_In_ LPCWSTR lpName);
|
||
// 移除不需要的信息项名。
|
||
PKGREAD_API BOOL RemovePackageApplicationItemGetName (_In_ LPCWSTR lpName);
|
||
// 获取现在有的信息项名。读取时将指针数组的成员转换为 LPCWSTR 读取,且不能修改。
|
||
// 注意:返回的 HLIST_PVOID 要经过 DestroyApplicationItemsName 销毁。
|
||
PKGREAD_API HLIST_PVOID GetAllApplicationItemsName ();
|
||
// 通过 GetAllApplicationItemsName 获取的 HLIST_PVOID 由 DestroyApplicationItemsName 销毁。
|
||
PKGREAD_API void DestroyApplicationItemsName (_In_ HLIST_PVOID hList);
|
||
// 获取到 Application 信息枚举器。在自己缓存完信息前不要销毁,直到再也不需要后才销毁。
|
||
// 通过 GetPackageApplications 获取的 HAPPENUMERATOR 由 DestroyApplicationsMap 销毁
|
||
PKGREAD_API HAPPENUMERATOR GetPackageApplications (_In_ HPKGREAD hReader);
|
||
// 从 Application 枚举器转换成 HLIST_PVOID { HLIST_PVOID {HPAIR_PVOID} } (类似于多个映射组成的数组)。
|
||
// 读取最深层的指针成员转换为 LPCWSTR 读取。其 LPCWSTR 周期随着 HAPPENUMERATOR 的周期而决定。
|
||
PKGREAD_API HLIST_PVOID ApplicationsToMap (_In_ HAPPENUMERATOR hEnumerator);
|
||
// 通过 ApplicationsToMap 获取的 HLIST_PVOID 由 DestroyApplicationsMap 销毁
|
||
PKGREAD_API void DestroyApplicationsMap (_In_ HLIST_PVOID hEnumerator);
|
||
// 通过 GetPackageApplications 获取的 HAPPENUMERATOR 由 DestroyApplicationsMap 销毁
|
||
PKGREAD_API void DestroyPackageApplications (_In_ HAPPENUMERATOR hEnumerator);
|
||
|
||
// Resources
|
||
#ifndef _TYPE_STRUCT_LIST_LCID_
|
||
#define _TYPE_STRUCT_LIST_LCID_
|
||
typedef struct _LIST_LCID
|
||
{
|
||
DWORD dwSize _DEFAULT_INIT_VALUE_ (0);
|
||
LCID aLcid [1] _DEFAULT_INIT_VALUE_ ({0});
|
||
} LIST_LCID, *HLIST_LCID;
|
||
#endif
|
||
#ifndef _TYPE_STRUCT_LIST_UINT32_
|
||
#define _TYPE_STRUCT_LIST_UINT32_
|
||
typedef struct _LIST_UINT32
|
||
{
|
||
DWORD dwSize _DEFAULT_INIT_VALUE_ (0);
|
||
LCID aUI32 [1] _DEFAULT_INIT_VALUE_ ({0});
|
||
} LIST_UINT32, *HLIST_UINT32;
|
||
#endif
|
||
// 返回区域代码 (Locale Code) 数组。以 LPWSTR 读取。注:一定要通过 DestroyResourcesLanguagesList 释放
|
||
PKGREAD_API HLIST_PVOID GetResourcesLanguages (_In_ HPKGREAD hReader);
|
||
// 返回将区域代码转换成 LCID(如 en-US 为 1033,zh-CN 为 2052) 后的数组。以 UINT32 读取。
|
||
// 注:一定要通过 DestroyResourcesLanguagesLcidList 释放
|
||
PKGREAD_API HLIST_LCID GetResourcesLanguagesToLcid (_In_ HPKGREAD hReader);
|
||
// 返回 DPI 支持(如 100,125) 的数组。
|
||
// 注:一定要通过 DestroyResourcesScalesList 宏(或 DestroyUInt32List 函数)释放
|
||
PKGREAD_API HLIST_UINT32 GetResourcesScales (_In_ HPKGREAD hReader);
|
||
#define PKG_RESOURCES_DXFEATURE_LEVEL9 0x1
|
||
#define PKG_RESOURCES_DXFEATURE_LEVEL10 0x2
|
||
#define PKG_RESOURCES_DXFEATURE_LEVEL11 0x4
|
||
#define PKG_RESOURCES_DXFEATURE_LEVEL12 0x8
|
||
#define PKG_RESOURCES_DXFEATURE_UNSPECIFIED 0
|
||
// 返回一个 DWORD 值。通过按位与来获取支持的 DirectX 功能支持。如果等于 0 则意味着都不支持。该值不必释放。
|
||
PKGREAD_API DWORD GetResourcesDxFeatureLevels (_In_ HPKGREAD hReader);
|
||
// 销毁 GetResourcesLanguages 获取的数组
|
||
PKGREAD_API void DestroyResourcesLanguagesList (_In_ HLIST_PVOID hList);
|
||
// 销毁 GetResourcesLanguagesToLcid 获取的数组
|
||
PKGREAD_API void DestroyResourcesLanguagesLcidList (_In_ HLIST_LCID hList);
|
||
PKGREAD_API void DestroyUInt32List (_In_ HLIST_UINT32 hList);
|
||
// 销毁 GetResourcesScales 获取的数组
|
||
#define DestroyResourcesScalesList DestroyUInt32List
|
||
|
||
// Dependencies
|
||
#ifndef _TYPE_STRUCT_DEPENDENCY_
|
||
#define _TYPE_STRUCT_DEPENDENCY_
|
||
typedef struct _DEPENDENCY_INFO
|
||
{
|
||
VERSION verMin;
|
||
LPWSTR lpName _DEFAULT_INIT_VALUE_ (NULL);
|
||
LPWSTR lpPublisher _DEFAULT_INIT_VALUE_ (NULL);
|
||
} DEPENDENCY_INFO;
|
||
#endif
|
||
#ifndef _TYPE_STRUCT_DEPENDENCY_LIST_
|
||
#define _TYPE_STRUCT_DEPENDENCY_LIST_
|
||
typedef struct _LIST_DEPINFO
|
||
{
|
||
DWORD dwSize _DEFAULT_INIT_VALUE_ (0);
|
||
DEPENDENCY_INFO aDepInfo [1];
|
||
} LIST_DEPINFO, *HLIST_DEPINFO;
|
||
#endif
|
||
// 获取依赖项信息数组,返回 HLIST_DEPINFO。必须由 DestroyDependencesInfoList 销毁
|
||
PKGREAD_API HLIST_DEPINFO GetDependencesInfoList (_In_ HPKGREAD hReader);
|
||
// 通过 GetDependencesInfoList 返回的指针由此销毁
|
||
PKGREAD_API void DestroyDependencesInfoList (_In_ HLIST_DEPINFO hList);
|
||
|
||
// Capabilities
|
||
PKGREAD_API HLIST_PVOID GetCapabilitiesList (_In_ HPKGREAD hReader);
|
||
PKGREAD_API HLIST_PVOID GetDeviceCapabilitiesList (_In_ HPKGREAD hReader);
|
||
PKGREAD_API void DestroyWStringList (_In_ HLIST_PVOID hList);
|
||
#define DestroyCapabilitiesList DestroyWStringList
|
||
#define DestroyDeviceCapabilitiesList DestroyWStringList
|
||
|
||
// Prerequisite
|
||
#define PKG_PREREQUISITE_OS_MIN_VERSION L"OSMinVersion"
|
||
#define PKG_PREREQUISITE_OS_MAX_VERSION_TESTED L"OSMaxVersionTested"
|
||
PKGREAD_API BOOL GetPackagePrerequisite (_In_ HPKGREAD hReader, _In_ LPCWSTR lpName, _Outptr_ VERSION *pVerRet);
|
||
#define GetPackagePrerequisiteOsMinVersion(_In_hReader_, _Outptr_pVerRet_) GetPackagePrerequisite (_In_hReader_, PKG_PREREQUISITE_OS_MIN_VERSION, _Outptr_pVerRet_)
|
||
#define GetPackagePrerequisiteOsMaxVersionTested(_In_hReader_, _Outptr_pVerRet_) GetPackagePrerequisite (_In_hReader_, PKG_PREREQUISITE_OS_MAX_VERSION_TESTED, _Outptr_pVerRet_)
|
||
PKGREAD_API LPWSTR GetPackagePrerequistieSystemVersionName (_In_ HPKGREAD hReader, _In_ LPCWSTR lpName);
|
||
|
||
// File Stream
|
||
// 从 Appx 包中获取 Appx 中的文件的文件流。
|
||
// 注:只提取 Payloads 文件。不可提供 Footprint 文件。
|
||
// 对于 AppxBundle 包,则随机从一个应用包中提取文件。
|
||
PKGREAD_API HANDLE GetAppxFileFromAppxPackage (_In_ HPKGREAD hReader, _In_ LPCWSTR lpFileName);
|
||
// 从 AppxBundle 包中获取 Appx 子包的文件流。
|
||
PKGREAD_API HANDLE GetAppxBundlePayloadPackageFile (_In_ HPKGREAD hReader, _In_ LPCWSTR lpFileName);
|
||
// 从 Appx 包中获取 Appx 的 Pri 文件流
|
||
// 对于 AppxBundle 包,则随机从一个应用包中提取 Pri 文件。
|
||
PKGREAD_API HANDLE GetAppxPriFileStream (_In_ HPKGREAD hReader);
|
||
// 从 AppxBundle 包中获取的子包的文件流中提取包中的文件
|
||
// 注:只提取 Payloads 文件。不可提供 Footprint 文件。
|
||
PKGREAD_API HANDLE GetFileFromPayloadPackage (_In_ HANDLE hPackageStream, _In_ LPCWSTR lpFileName);
|
||
// 从 AppxBundle 包中获取的子包的文件流中提取 Pri 文件流
|
||
PKGREAD_API HANDLE GetPriFileFromPayloadPackage (_In_ HANDLE hPackageStream);
|
||
// 从 AppxBundle 包中获取合适的包,合适指的是资源合适。
|
||
// 第一个用于返回的参数指的是返回的语言合适的选项,第二个用于返回的参数是返回的缩放资源。
|
||
// 如果指向的都是同一个包,那么两个参数返回的都是同一个指针。
|
||
// 对于 Appx 文件直接返回假。
|
||
PKGREAD_API BOOL GetSuitablePackageFromBundle (_In_ HPKGREAD hReader, _Outptr_ HANDLE *pStreamForLang, _Outptr_ HANDLE *pStreamForScale);
|
||
// 文件流必须通过此来释放。
|
||
PKGREAD_API ULONG DestroyAppxFileStream (_In_ HANDLE hFileStream);
|
||
// 转换:文件流转换到 Data URL。这样转换后浏览器可以使用图片。
|
||
// 注意:dwCharCount 指的是 lpMimeBuf 的可容纳字符数,如 WCHAR lpMimeBuf [dwCharCount],不是实际可容纳字节数。
|
||
// 返回的非空指针需要通过 free 释放。lpBase64Head 返回的是 Base64 编码后的数据,为返回指针指向的部分。
|
||
// 如字符串为 data:text/plain;base64,SGVsbG8sIFdvcmxkIQ%3D%3D
|
||
// 那么: ↑ lpBase64Head 指向于“base64,”后的第一个字符。
|
||
PKGREAD_API LPWSTR StreamToBase64W (_In_ HANDLE hFileStream, _Out_writes_ (dwCharCount) LPWSTR lpMimeBuf, _In_ DWORD dwCharCount, _Outptr_ LPWSTR *lpBase64Head);
|
||
// 获取 AppxBundle 包中的应用包文件流。最后通过 DestroyAppxFileStream 销毁。
|
||
PKGREAD_API HANDLE GetAppxBundleApplicationPackageFile (_In_ HPKGREAD hReader);
|
||
// 获取功能名的显示名,如 internetClient 对应“访问您的 Internet 连接”。返回的是适应于系统区域语言的文本。
|
||
// 注意:返回的字符串一定要通过 free 释放。
|
||
PKGREAD_API LPWSTR GetPackageCapabilityDisplayName (LPCWSTR lpCapabilityName);
|
||
// 释放从本库中返回的字符串
|
||
// 其实通过 free 释放即可,但考虑到环境问题,那么另写了个函数
|
||
PKGREAD_API void PackageReaderFreeString (LPWSTR lpStrFromThisDll);
|
||
|
||
PKGREAD_API HLIST_PVOID GetAppxBundleAllResourcePackageFileNames (_In_ HPKGREAD hReader);
|
||
|
||
PKGREAD_API HLIST_PVOID GetAppxBundleAllLocaleResourcePackageFileNames (_In_ HPKGREAD hReader);
|
||
|
||
PKGREAD_API HLIST_PVOID GetAppxBundleAllFileResourcePackageFileNames (_In_ HPKGREAD hReader);
|
||
PKGREAD_API void FreeAppxBundlePayloadsFileNameList (_In_ HLIST_PVOID hStringList);
|
||
|
||
PKGREAD_API void UpdatePackageApplicationItemGetName (_In_ LPCWSTR *lpNames, _In_ DWORD dwArrLen);
|
||
typedef void (*ITER_WSTRING_CALLBACK) (LPCWSTR lpString);
|
||
PKGREAD_API void GetPackageApplicationItemGetNameList (_In_ ITER_WSTRING_CALLBACK pfCallback);
|
||
// ========= 以下是针对于应用清单的读取器,一些常量和类型等是复用的 =========
|
||
|
||
TEMPLATE_STRUCT (PKGMANIFESTREAD);
|
||
typedef PKGMANIFESTREAD *HPKGMANIFESTREAD;
|
||
// 创建 Manifest 读取器。
|
||
// 返回一个 Manifest Reader 句柄,初始状态未加载任何文件。
|
||
PKGREAD_API HPKGMANIFESTREAD CreateManifestReader ();
|
||
// 从文件加载 Manifest。
|
||
// 支持的输入:
|
||
// - AppxManifest.xml
|
||
// - .appx / .msix
|
||
// - .appxbundle / .msixbundle
|
||
// 加载成功后,读取器会自动识别 Manifest 类型。
|
||
PKGREAD_API BOOL LoadManifestFromFile (_In_ HPKGMANIFESTREAD hReader, _In_ LPCWSTR lpFilePath);
|
||
// 从文件加载 Manifest。
|
||
// 支持的输入:
|
||
// - AppxManifest.xml
|
||
// - .appx / .msix
|
||
// - .appxbundle / .msixbundle
|
||
// 加载成功后,读取器会自动识别 Manifest 类型。
|
||
PKGREAD_API BOOL LoadManifestFromFile (_In_ HPKGMANIFESTREAD hReader, _In_ LPCWSTR lpFilePath);
|
||
// 销毁 Manifest 读取器(必须调用)。
|
||
// 释放内部所有资源,句柄在此之后不可再使用。
|
||
PKGREAD_API void DestroyManifestReader (_In_ HPKGMANIFESTREAD hReader);
|
||
// 获取 Manifest 的类型。
|
||
// 返回值:
|
||
// - PKGTYPE_APPX :单一 Appx / Msix 包
|
||
// - PKGTYPE_BUNDLE :AppxBundle / MsixBundle
|
||
// - PKGTYPE_UNKNOWN :未知或未加载
|
||
PKGREAD_API WORD GetManifestType (_In_ HPKGMANIFESTREAD hReader);
|
||
// 获取 Manifest 的类型。
|
||
// 返回值:
|
||
// - PKGTYPE_APPX :单一 Appx / Msix 包
|
||
// - PKGTYPE_BUNDLE :AppxBundle / MsixBundle
|
||
// - PKGTYPE_UNKNOWN :未知或未加载
|
||
PKGREAD_API WORD GetManifestType (_In_ HPKGMANIFESTREAD hReader);
|
||
// 判断 Manifest 是否有效。
|
||
// 如果 Manifest 解析失败、结构非法或未加载,返回 FALSE。
|
||
PKGREAD_API BOOL IsManifestValid (_In_ HPKGMANIFESTREAD hReader);
|
||
// 获取 Manifest 所表示包的角色。
|
||
// 返回值:
|
||
// - PKGROLE_APPLICATION :应用包
|
||
// - PKGROLE_FRAMEWORK :框架包
|
||
// - PKGROLE_RESOURCE :资源包
|
||
// - PKGROLE_UNKNOWN :未知
|
||
//
|
||
// 说明:
|
||
// - 对于 AppxBundle,永远返回 PKGROLE_APPLICATION。
|
||
PKGREAD_API WORD GetManifestRole (_In_ HPKGMANIFESTREAD hReader);
|
||
// 获取 Identity 的字符串字段。
|
||
// dwName 可取值:
|
||
// - PKG_IDENTITY_NAME
|
||
// - PKG_IDENTITY_PUBLISHER
|
||
// - PKG_IDENTITY_PACKAGEFAMILYNAME
|
||
// - PKG_IDENTITY_PACKAGEFULLNAME
|
||
// - PKG_IDENTITY_RESOURCEID
|
||
//
|
||
// 返回值:
|
||
// - 成功:返回新分配的字符串(调用者负责释放)
|
||
// - 失败:返回 NULL
|
||
PKGREAD_API LPWSTR GetManifestIdentityStringValue (_In_ HPKGMANIFESTREAD hReader, _In_ DWORD dwName);
|
||
#define GetManifestIdentityName(_In_hReader_) GetManifestIdentityStringValue (_In_hReader_, PKG_IDENTITY_NAME)
|
||
#define GetManifestIdentityPublisher(_In_hReader_) GetManifestIdentityStringValue (_In_hReader_, PKG_IDENTITY_PUBLISHER)
|
||
#define GetManifestIdentityPackageFamilyName(_In_hReader_) GetManifestIdentityStringValue (_In_hReader_, PKG_IDENTITY_PACKAGEFAMILYNAME)
|
||
#define GetManifestIdentityPackageFullName(_In_hReader_) GetManifestIdentityStringValue (_In_hReader_, PKG_IDENTITY_PACKAGEFULLNAME)
|
||
#define GetManifestIdentityResourceId(_In_hReader_) GetManifestIdentityStringValue (_In_hReader_, PKG_IDENTITY_RESOURCEID)
|
||
// 获取 Identity 的版本号。
|
||
//
|
||
// pVersion 返回格式化后的 VERSION 结构。
|
||
// 返回值:
|
||
// - TRUE :成功
|
||
// - FALSE :失败或版本不存在
|
||
PKGREAD_API BOOL GetManifestIdentityVersion (_In_ HPKGMANIFESTREAD hReader, _Out_ VERSION *pVersion);
|
||
// 获取包支持的架构信息。
|
||
// 对于单一 Appx 包,返回单一架构;
|
||
// 对于 Bundle,返回所有子包架构的组合(按位或)。
|
||
//
|
||
// 返回值通过 pdwArchi 输出,取值为 PKG_ARCHITECTURE_* 宏。
|
||
PKGREAD_API BOOL GetManifestIdentityArchitecture (_In_ HPKGMANIFESTREAD hReader, _Out_ DWORD *pdwArchi);
|
||
// 获取 Properties 中的字符串值。
|
||
// lpName 为属性名(如 "DisplayName")。
|
||
// 返回值:
|
||
// - 成功:返回新分配的字符串(调用者负责释放)
|
||
// - 失败:返回 NULL
|
||
//
|
||
// 说明:
|
||
// - 仅适用于单一 Appx 包。
|
||
PKGREAD_API LPWSTR GetManifestPropertiesStringValue (_In_ HPKGMANIFESTREAD hReader, _In_ LPCWSTR lpName);
|
||
// 获取 Properties 中的布尔值。
|
||
//
|
||
// pRet 返回布尔结果。
|
||
// 返回 HRESULT,便于区分失败原因。
|
||
//
|
||
// 说明:
|
||
// - 仅适用于单一 Appx 包。
|
||
PKGREAD_API HRESULT GetManifestPropertiesBoolValue (_In_ HPKGMANIFESTREAD hReader, _In_ LPCWSTR lpName, _Outptr_ BOOL *pRet);
|
||
// 向应用枚举器中添加需要读取的 Application 属性名。
|
||
// 返回 FALSE 表示属性名非法或重复。
|
||
PKGREAD_API BOOL AddManifestApplicationItemGetName (_In_ LPCWSTR lpName);
|
||
// 从应用枚举器中移除指定的 Application 属性名。
|
||
PKGREAD_API BOOL RemoveManifestApplicationItemGetName (_In_ LPCWSTR lpName);
|
||
// 获取 Applications 枚举器。
|
||
// 返回一个应用枚举器句柄,调用者需手动销毁。
|
||
//
|
||
// 说明:
|
||
// - 仅适用于单一 Appx 包。
|
||
PKGREAD_API HAPPENUMERATOR GetManifestApplications (_In_ HPKGMANIFESTREAD hReader);
|
||
// 销毁 Applications 枚举器。
|
||
PKGREAD_API void DestroyManifestApplications (_In_ HAPPENUMERATOR hEnumerator);
|
||
// 获取资源支持的语言列表(字符串形式)。
|
||
// 返回 HLIST_PVOID,内部元素为 LPWSTR。
|
||
PKGREAD_API HLIST_PVOID GetManifestResourcesLanguages (_In_ HPKGMANIFESTREAD hReader);
|
||
// 获取资源支持的语言列表(LCID 形式)。
|
||
// 返回 HLIST_LCID。
|
||
PKGREAD_API HLIST_LCID GetManifestResourcesLanguagesToLcid (_In_ HPKGMANIFESTREAD hReader);
|
||
// 获取资源支持的缩放比例(Scale)。
|
||
// 返回 HLIST_UINT32。
|
||
PKGREAD_API HLIST_UINT32 GetManifestResourcesScales (_In_ HPKGMANIFESTREAD hReader);
|
||
// 获取资源支持的 DirectX Feature Level。
|
||
// 返回值为 PKG_RESOURCES_DXFEATURE_LEVEL* 位掩码组合。
|
||
PKGREAD_API DWORD GetManifestResourcesDxFeatureLevels (_In_ HPKGMANIFESTREAD hReader);
|
||
// 获取依赖包信息列表。
|
||
// 返回 HLIST_DEPINFO,其中包含名称、发布者及最低版本。
|
||
//
|
||
// 说明:
|
||
// - 仅适用于单一 Appx 包。
|
||
PKGREAD_API HLIST_DEPINFO GetManifestDependencesInfoList (_In_ HPKGMANIFESTREAD hReader);
|
||
// 获取 Capability 列表(Capability)。
|
||
// 返回的列表元素为 LPWSTR。
|
||
//
|
||
// 说明:
|
||
// - 仅适用于单一 Appx 包。
|
||
PKGREAD_API HLIST_PVOID GetManifestCapabilitiesList (_In_ HPKGMANIFESTREAD hReader);
|
||
// 获取 Device Capability 列表。
|
||
// 返回的列表元素为 LPWSTR。
|
||
//
|
||
// 说明:
|
||
// - 仅适用于单一 Appx 包。
|
||
PKGREAD_API HLIST_PVOID GetManifestDeviceCapabilitiesList (_In_ HPKGMANIFESTREAD hReader);
|
||
// 获取指定前置条件的最低版本要求。
|
||
// lpName 为前置组件名称。
|
||
// pVerRet 返回版本结构。
|
||
// 返回 TRUE 表示存在该前置条件。
|
||
PKGREAD_API BOOL GetManifestPrerequisite (_In_ HPKGMANIFESTREAD hReader, _In_ LPCWSTR lpName, _Outptr_ VERSION *pVerRet);
|
||
|
||
PKGREAD_API LPWSTR GetManifestPrerequistieSystemVersionName (_In_ HPKGMANIFESTREAD hReader, _In_ LPCWSTR lpName);
|
||
|
||
PKGREAD_API BOOL PackageReaderGetFileRoot (_In_ LPWSTR lpFilePath);
|
||
|
||
PKGREAD_API LPWSTR PackageReaderCombinePath (_In_ LPCWSTR lpLeft, _In_ LPCWSTR lpRight, _Outptr_ LPWSTR lpBuf);
|
||
|
||
PKGREAD_API HANDLE PackageReaderGetFileStream (LPCWSTR lpFilePath);
|
||
|
||
PKGREAD_API void PackageReaderDestroyFileStream (HANDLE hStream);
|
||
|
||
#ifdef _DEFAULT_INIT_VALUE_
|
||
#undef _DEFAULT_INIT_VALUE_
|
||
#endif
|
||
#ifdef _DEFAULT_INIT_VALUE_FORFUNC_
|
||
#undef _DEFAULT_INIT_VALUE_FORFUNC_
|
||
#endif
|
||
#ifdef __cplusplus
|
||
}
|
||
#endif
|
||
|
||
#if defined (__cplusplus)
|
||
#include <cstdlib>
|
||
#include <string>
|
||
#include <map>
|
||
#include <vector>
|
||
#include <functional>
|
||
#include <cstring>
|
||
#include <Shlwapi.h>
|
||
#include <algorithm>
|
||
//#include "..\priformatcli\priformatcli.h"
|
||
const std::vector <std::wstring> g_filepathitems =
|
||
{
|
||
L"LockScreenLogo",
|
||
L"Logo",
|
||
L"SmallLogo",
|
||
L"Square150x150Logo",
|
||
L"Square30x30Logo",
|
||
L"Square310x310Logo",
|
||
L"Square44x44Logo",
|
||
L"Square70x70Logo",
|
||
L"Square71x71Logo",
|
||
L"StartPage",
|
||
L"Tall150x310Logo",
|
||
L"VisualGroup",
|
||
L"WideLogo",
|
||
L"Wide310x150Logo",
|
||
L"Executable"
|
||
};
|
||
std::map <std::wstring, std::wstring> g_capnamemap;
|
||
std::wstring GetPackageCapabilityDisplayName (const std::wstring &capname)
|
||
{
|
||
try
|
||
{
|
||
if (g_capnamemap.find (capname) != g_capnamemap.end () && !g_capnamemap.at (capname).empty ()) return g_capnamemap.at (capname);
|
||
else
|
||
{
|
||
LPWSTR lpstr = GetPackageCapabilityDisplayName (capname.c_str ());
|
||
std::wstring ret = L"";
|
||
ret += lpstr ? lpstr : L"";
|
||
if (lpstr) free (lpstr);
|
||
lpstr = nullptr;
|
||
g_capnamemap [capname] = ret;
|
||
return ret;
|
||
}
|
||
}
|
||
catch (...)
|
||
{
|
||
LPWSTR lpstr = GetPackageCapabilityDisplayName (capname.c_str ());
|
||
std::wstring ret = L"";
|
||
ret += lpstr ? lpstr : L"";
|
||
if (lpstr) free (lpstr);
|
||
lpstr = nullptr;
|
||
g_capnamemap [capname] = ret;
|
||
return ret;
|
||
}
|
||
return L"";
|
||
}
|
||
class package_reader
|
||
{
|
||
private:
|
||
HPKGREAD hReader = nullptr;
|
||
std::wstring filepath = L"";
|
||
bool usepri = false;
|
||
bool resswitch = false;
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
prifilebundle pribundlereader;
|
||
std::vector <IStream *> prifilestreams;
|
||
#endif
|
||
|
||
void initpri ()
|
||
{
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
pribundlereader.destroy ();
|
||
for (auto &it : prifilestreams)
|
||
{
|
||
if (it != nullptr)
|
||
{
|
||
DestroyAppxFileStream (it);
|
||
it = nullptr;
|
||
}
|
||
}
|
||
prifilestreams.clear ();
|
||
switch (this->package_type ())
|
||
{
|
||
case PKGTYPE_APPX: {
|
||
IStream *pristream = (IStream *)GetAppxPriFileStream (hReader);
|
||
if (pristream)
|
||
{
|
||
prifilestreams.push_back (pristream);
|
||
pribundlereader.set (3, pristream);
|
||
}
|
||
} break;
|
||
case PKGTYPE_BUNDLE: {
|
||
HANDLE hls = nullptr, hss = nullptr;
|
||
destruct rel1 ([&hls, &hss] () {
|
||
if (hls == hss) hss = nullptr;
|
||
if (hls) DestroyAppxFileStream (hls);
|
||
if (hss) DestroyAppxFileStream (hss);
|
||
});
|
||
GetSuitablePackageFromBundle (hReader, &hls, &hss);
|
||
HANDLE hlpri = GetPriFileFromPayloadPackage (hls),
|
||
hspri = GetPriFileFromPayloadPackage (hss);
|
||
IStream *ls = (IStream *)hls, *ss = (IStream *)hss;
|
||
switch ((bool)ls << 1 | (bool)ss)
|
||
{
|
||
case 0b01:
|
||
case 0b10: {
|
||
if (hlpri) pribundlereader.set (1, (IStream *)hlpri);
|
||
if (hspri) pribundlereader.set (2, (IStream *)hspri);
|
||
if (hlpri) prifilestreams.push_back ((IStream *)hlpri);
|
||
if (hspri) prifilestreams.push_back ((IStream *)hspri);
|
||
HANDLE hd = GetAppxBundleApplicationPackageFile (hReader);
|
||
destruct relthd ([&hd] () {
|
||
if (hd) DestroyAppxFileStream (hd);
|
||
});
|
||
HANDLE hdpri = GetPriFileFromPayloadPackage (hd);
|
||
if (hd) pribundlereader.set (3, (IStream *)hd);
|
||
if (hd) prifilestreams.push_back ((IStream *)hdpri);
|
||
} break;
|
||
case 0b11: {
|
||
if (ls) pribundlereader.set (1, (IStream *)hlpri);
|
||
if (ss) pribundlereader.set (2, (IStream *)hspri);
|
||
if (ls && hlpri) prifilestreams.push_back ((IStream *)hlpri);
|
||
if (ss && hspri) prifilestreams.push_back ((IStream *)hspri);
|
||
} break;
|
||
default:
|
||
case 0b00: {
|
||
IStream *pkgstream = (IStream *)GetAppxBundleApplicationPackageFile (hReader);
|
||
destruct relthd ([&pkgstream] () {
|
||
if (pkgstream) DestroyAppxFileStream (pkgstream);
|
||
});
|
||
IStream *pristream = (IStream *)GetPriFileFromPayloadPackage (pkgstream);
|
||
if (pristream)
|
||
{
|
||
prifilestreams.push_back (pristream);
|
||
pribundlereader.set (3, pristream);
|
||
}
|
||
} break;
|
||
}
|
||
} break;
|
||
}
|
||
std::sort (prifilestreams.begin (), prifilestreams.end ());
|
||
auto last = std::unique (prifilestreams.begin (), prifilestreams.end ());
|
||
prifilestreams.erase (last, prifilestreams.end ());
|
||
bool lastvalue = resswitch;
|
||
resswitch = false;
|
||
try
|
||
{
|
||
std::vector <std::wstring> resnames;
|
||
{
|
||
auto prop = get_properties ();
|
||
std::wstring temp = prop.description ();
|
||
if (IsMsResourcePrefix (temp.c_str ())) resnames.push_back (temp);
|
||
temp = prop.display_name ();
|
||
if (IsMsResourcePrefix (temp.c_str ())) resnames.push_back (temp);
|
||
temp = prop.publisher_display_name ();
|
||
if (IsMsResourcePrefix (temp.c_str ())) resnames.push_back (temp);
|
||
resnames.push_back (prop.logo ());
|
||
}
|
||
{
|
||
auto app = get_applications ();
|
||
std::vector <application> apps;
|
||
app.get (apps);
|
||
for (auto &it_map : apps)
|
||
{
|
||
for (auto &it_item : it_map)
|
||
{
|
||
if (std::find (g_filepathitems.begin (), g_filepathitems.end (), it_item.first) != g_filepathitems.end () && !it_item.second.empty ())
|
||
resnames.push_back (it_item.second);
|
||
else if (IsMsResourcePrefix (it_item.second.c_str ())) resnames.push_back (it_item.second);
|
||
}
|
||
}
|
||
}
|
||
pribundlereader.add_search (resnames);
|
||
}
|
||
catch (const std::exception &e) {}
|
||
resswitch = lastvalue;
|
||
#endif
|
||
}
|
||
typedef struct deconstr
|
||
{
|
||
std::function <void ()> endtask = nullptr;
|
||
deconstr (std::function <void ()> pf): endtask (pf) {}
|
||
~deconstr () { if (endtask) endtask (); }
|
||
} destruct;
|
||
public:
|
||
class base_subitems
|
||
{
|
||
protected:
|
||
HPKGREAD &hReader;
|
||
public:
|
||
base_subitems (HPKGREAD &hReader): hReader (hReader) {}
|
||
};
|
||
class identity: public base_subitems
|
||
{
|
||
using base = base_subitems;
|
||
public:
|
||
using base::base;
|
||
std::wstring string_value (DWORD dwName) const
|
||
{
|
||
LPWSTR lpstr = nullptr;
|
||
deconstr rel ([&lpstr] () {
|
||
if (lpstr) free (lpstr);
|
||
lpstr = nullptr;
|
||
});
|
||
lpstr = GetPackageIdentityStringValue (hReader, dwName);
|
||
return lpstr ? lpstr : L"";
|
||
}
|
||
std::wstring name () const { return string_value (PKG_IDENTITY_NAME); }
|
||
std::wstring publisher () const { return string_value (PKG_IDENTITY_PUBLISHER); }
|
||
std::wstring package_family_name () const { return string_value (PKG_IDENTITY_PACKAGEFAMILYNAME); }
|
||
std::wstring package_full_name () const { return string_value (PKG_IDENTITY_PACKAGEFULLNAME); }
|
||
std::wstring resource_id () const { return string_value (PKG_IDENTITY_RESOURCEID); }
|
||
VERSION version (bool read_subpkg_ver = false) const { VERSION ver; GetPackageIdentityVersion (hReader, &ver, read_subpkg_ver); return ver; }
|
||
DWORD architecture () const { DWORD dw = 0; GetPackageIdentityArchitecture (hReader, &dw); return dw; }
|
||
};
|
||
class properties: public base_subitems
|
||
{
|
||
using base = base_subitems;
|
||
public:
|
||
using base::base;
|
||
std::wstring string_value (const std::wstring &swName) const
|
||
{
|
||
LPWSTR lpstr = nullptr;
|
||
deconstr rel ([&lpstr] () {
|
||
if (lpstr) free (lpstr);
|
||
lpstr = nullptr;
|
||
});
|
||
lpstr = GetPackagePropertiesStringValue (hReader, swName.c_str ());
|
||
return lpstr ? lpstr : L"";
|
||
}
|
||
bool bool_value (const std::wstring &swName, bool bRetWhenFailed = false) const
|
||
{
|
||
BOOL ret = FALSE;
|
||
HRESULT hr = GetPackagePropertiesBoolValue (hReader, swName.c_str (), &ret);
|
||
if (FAILED (hr)) return bRetWhenFailed;
|
||
else return ret != FALSE;
|
||
}
|
||
std::wstring display_name (bool toprires = true)
|
||
{
|
||
std::wstring ret = string_value (PKG_PROPERTIES_DISPLAYNAME);
|
||
if (!toprires) return ret;
|
||
if (!enable_pri ()) return ret;
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
else
|
||
{
|
||
if (!IsMsResourcePrefix (ret.c_str ())) return ret;
|
||
std::wstring privalue = pri_get_res (ret);
|
||
if (privalue.empty ()) return ret;
|
||
return privalue;
|
||
}
|
||
#endif
|
||
return ret;
|
||
}
|
||
std::wstring publisher_display_name (bool toprires = true)
|
||
{
|
||
std::wstring ret = string_value (PKG_PROPERTIES_PUBLISHER);
|
||
if (!toprires) return ret;
|
||
if (!enable_pri ()) return ret;
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
else
|
||
{
|
||
if (!IsMsResourcePrefix (ret.c_str ())) return ret;
|
||
std::wstring privalue = pri_get_res (ret);
|
||
if (privalue.empty ()) return ret;
|
||
return privalue;
|
||
}
|
||
#endif
|
||
return ret;
|
||
}
|
||
std::wstring description (bool toprires = true)
|
||
{
|
||
std::wstring ret = string_value (PKG_PROPERTIES_DESCRIPTION);
|
||
if (!toprires) return ret;
|
||
if (!enable_pri ()) return ret;
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
else
|
||
{
|
||
if (!IsMsResourcePrefix (ret.c_str ())) return ret;
|
||
std::wstring privalue = pri_get_res (ret);
|
||
if (privalue.empty ()) return ret;
|
||
return privalue;
|
||
}
|
||
#endif
|
||
return ret;
|
||
}
|
||
std::wstring logo (bool toprires = true)
|
||
{
|
||
std::wstring ret = string_value (PKG_PROPERTIES_LOGO);
|
||
if (!toprires) return ret;
|
||
if (!enable_pri ()) return ret;
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
else
|
||
{
|
||
std::wstring privalue = pri_get_res (ret);
|
||
if (privalue.empty ()) return ret;
|
||
return privalue;
|
||
}
|
||
#endif
|
||
return ret;
|
||
}
|
||
std::wstring logo_base64 ()
|
||
{
|
||
switch (GetPackageType (hReader))
|
||
{
|
||
case PKGTYPE_APPX: {
|
||
HANDLE pic = GetAppxFileFromAppxPackage (hReader, logo ().c_str ());
|
||
destruct relp ([&pic] () {
|
||
if (pic) DestroyAppxFileStream (pic);
|
||
pic = nullptr;
|
||
});
|
||
LPWSTR lpstr = nullptr;
|
||
destruct rel ([&lpstr] () {
|
||
if (lpstr) free (lpstr);
|
||
lpstr = nullptr;
|
||
});
|
||
lpstr = StreamToBase64W (pic, nullptr, 0, nullptr);
|
||
return lpstr ? lpstr : L"";
|
||
} break;
|
||
case PKGTYPE_BUNDLE: {
|
||
HANDLE pkg = nullptr, pic = nullptr;
|
||
destruct relp ([&pic, &pkg] () {
|
||
if (pic == pkg) pkg = nullptr; // 虽然来说这个代码永远无法达到,但是保险起见
|
||
if (pic) DestroyAppxFileStream (pic);
|
||
if (pkg) DestroyAppxFileStream (pkg);
|
||
pkg = nullptr;
|
||
pic = nullptr;
|
||
});
|
||
GetSuitablePackageFromBundle (hReader, nullptr, &pkg);
|
||
pic = GetFileFromPayloadPackage (pkg, logo ().c_str ());
|
||
LPWSTR lpstr = nullptr;
|
||
destruct rel ([&lpstr] () {
|
||
if (lpstr) free (lpstr);
|
||
lpstr = nullptr;
|
||
});
|
||
lpstr = StreamToBase64W (pic, nullptr, 0, nullptr);
|
||
if (!(lpstr && *lpstr))
|
||
{
|
||
if (lpstr) free (lpstr);
|
||
HANDLE pkg1 = nullptr, pic1 = nullptr;
|
||
destruct relp1 ([&pic1, &pkg1] () {
|
||
if (pic1 == pkg1) pkg1 = nullptr; // 虽然来说这个代码永远无法达到,但是保险起见
|
||
if (pic1) DestroyAppxFileStream (pic1);
|
||
if (pkg1) DestroyAppxFileStream (pkg1);
|
||
pkg1 = nullptr;
|
||
pic1 = nullptr;
|
||
});
|
||
pkg1 = GetAppxBundleApplicationPackageFile (hReader);
|
||
if (pkg1 == pkg) pkg = nullptr;
|
||
if (pkg1)
|
||
{
|
||
pic1 = GetFileFromPayloadPackage (pkg1, logo ().c_str ());
|
||
lpstr = StreamToBase64W (pic1, nullptr, 0, nullptr);
|
||
}
|
||
}
|
||
return lpstr ? lpstr : L"";
|
||
} break;
|
||
}
|
||
return L"";
|
||
}
|
||
bool framework () const { return bool_value (PKG_PROPERTIES_FRAMEWORD); }
|
||
bool resource_package () const { return bool_value (PKG_PROPERTIES_IS_RESOURCE); }
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
prifilebundle *pbreader = nullptr;
|
||
bool *usepri = nullptr;
|
||
bool *resconvert = nullptr;
|
||
#endif
|
||
bool enable_pri () const
|
||
{
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
if (!pbreader) return false;
|
||
if (!usepri || !*usepri) return false;
|
||
if (!resconvert) return false;
|
||
return *resconvert;
|
||
#else
|
||
return false;
|
||
#endif
|
||
}
|
||
std::wstring pri_get_res (const std::wstring &resname)
|
||
{
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
if (resname.empty ()) return L"";
|
||
if (!pbreader) return L"";
|
||
return pbreader->resource (resname);
|
||
#else
|
||
return L"";
|
||
#endif
|
||
}
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
properties (HPKGREAD &hReader, prifilebundle *pri, bool *up, bool *resc):
|
||
base (hReader), pbreader (pri), usepri (up), resconvert (resc) {}
|
||
#endif
|
||
};
|
||
class application: public std::map <std::wstring, std::wstring>
|
||
{
|
||
using base = std::map <std::wstring, std::wstring>;
|
||
public:
|
||
using base::base;
|
||
application () = default;
|
||
std::wstring user_model_id () { return this->at (L"AppUserModelID"); }
|
||
friend bool operator == (application &a1, application &a2) { return !_wcsicmp (a1.user_model_id ().c_str (), a2.user_model_id ().c_str ()); }
|
||
friend bool operator != (application &a1, application &a2) { return _wcsicmp (a1.user_model_id ().c_str (), a2.user_model_id ().c_str ()); }
|
||
explicit operator bool () { return this->user_model_id ().empty (); }
|
||
std::wstring &operator [] (const std::wstring &key)
|
||
{
|
||
auto it = this->find (key);
|
||
if (it == this->end ())
|
||
{
|
||
it = this->insert (std::make_pair (key, L"")).first;
|
||
}
|
||
if (!enable_pri ()) return it->second;
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
if (IsMsResourcePrefix (it->second.c_str ()))
|
||
{
|
||
std::wstring privalue = pri_get_res (it->second);
|
||
if (!privalue.empty ()) return privalue;
|
||
return it->second;
|
||
}
|
||
else if (std::find (g_filepathitems.begin (), g_filepathitems.end (), it->first) != g_filepathitems.end () && !it->second.empty ())
|
||
{
|
||
std::wstring privalue = pri_get_res (it->second);
|
||
if (!privalue.empty ()) return privalue;
|
||
return it->second;
|
||
}
|
||
#endif
|
||
return it->second;
|
||
}
|
||
typename base::iterator find_case_insensitive (const std::wstring &key)
|
||
{
|
||
for (auto it = this->begin (); it != this->end (); ++it)
|
||
{
|
||
if (_wcsicmp (it->first.c_str (), key.c_str ()) == 0)
|
||
return it;
|
||
}
|
||
return this->end ();
|
||
}
|
||
typename base::const_iterator find_case_insensitive (const std::wstring &key) const
|
||
{
|
||
for (auto it = this->begin (); it != this->end (); ++ it)
|
||
{
|
||
if (_wcsicmp (it->first.c_str (), key.c_str ()) == 0)
|
||
return it;
|
||
}
|
||
return this->end ();
|
||
}
|
||
std::wstring at (const std::wstring &key)
|
||
{
|
||
auto it = this->find_case_insensitive (key);
|
||
if (it == this->end ()) throw std::out_of_range ("application::at: key not found");
|
||
if (!enable_pri ()) return it->second;
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
if (IsMsResourcePrefix (it->second.c_str ()))
|
||
{
|
||
std::wstring privalue = pri_get_res (it->second);
|
||
if (!privalue.empty ()) return privalue;
|
||
}
|
||
#endif
|
||
return it->second;
|
||
}
|
||
std::wstring newat (const std::wstring &key, bool to_pri_string = true)
|
||
{
|
||
auto it = this->find (key);
|
||
if (it == this->end ())
|
||
{
|
||
it = this->insert (std::make_pair (key, L"")).first;
|
||
}
|
||
if (!enable_pri () && to_pri_string) return it->second;
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
if (IsMsResourcePrefix (it->second.c_str ()))
|
||
{
|
||
std::wstring privalue = pri_get_res (it->second);
|
||
if (!privalue.empty ()) return privalue;
|
||
return it->second;
|
||
}
|
||
else if (std::find (g_filepathitems.begin (), g_filepathitems.end (), it->first) != g_filepathitems.end () && !it->second.empty ())
|
||
{
|
||
std::wstring privalue = pri_get_res (it->second);
|
||
if (!privalue.empty ()) return privalue;
|
||
return it->second;
|
||
}
|
||
#endif
|
||
return it->second;
|
||
}
|
||
// 仅支持文件
|
||
std::wstring newat_base64 (const std::wstring &key)
|
||
{
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
std::wstring value = newat (key);
|
||
if (std::find (g_filepathitems.begin (), g_filepathitems.end (), key) != g_filepathitems.end () && !value.empty ())
|
||
{
|
||
switch (GetPackageType (hReader))
|
||
{
|
||
case PKGTYPE_APPX: {
|
||
HANDLE pic = GetAppxFileFromAppxPackage (hReader, value.c_str ());
|
||
destruct relp ([&pic] () {
|
||
if (pic) DestroyAppxFileStream (pic);
|
||
pic = nullptr;
|
||
});
|
||
LPWSTR lpstr = nullptr;
|
||
destruct rel ([&lpstr] () {
|
||
if (lpstr) free (lpstr);
|
||
lpstr = nullptr;
|
||
});
|
||
lpstr = StreamToBase64W (pic, nullptr, 0, nullptr);
|
||
return lpstr ? lpstr : L"";
|
||
} break;
|
||
case PKGTYPE_BUNDLE: {
|
||
HANDLE pkg = nullptr, pic = nullptr;
|
||
destruct relp ([&pic, &pkg] () {
|
||
if (pic == pkg) pkg = nullptr; // 虽然来说这个代码永远无法达到,但是保险起见
|
||
if (pic) DestroyAppxFileStream (pic);
|
||
if (pkg) DestroyAppxFileStream (pkg);
|
||
pkg = nullptr;
|
||
pic = nullptr;
|
||
});
|
||
GetSuitablePackageFromBundle (hReader, nullptr, &pkg);
|
||
pic = GetFileFromPayloadPackage (pkg, value.c_str ());
|
||
LPWSTR lpstr = nullptr;
|
||
destruct rel ([&lpstr] () {
|
||
if (lpstr) free (lpstr);
|
||
lpstr = nullptr;
|
||
});
|
||
lpstr = StreamToBase64W (pic, nullptr, 0, nullptr);
|
||
return lpstr ? lpstr : L"";
|
||
} break;
|
||
}
|
||
return L"";
|
||
}
|
||
else return L"";
|
||
#else
|
||
return L"";
|
||
#endif
|
||
}
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
HPKGREAD hReader = nullptr;
|
||
prifilebundle *pbreader = nullptr;
|
||
bool *usepri = nullptr;
|
||
bool *resconvert = nullptr;
|
||
#endif
|
||
bool enable_pri () const
|
||
{
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
if (!pbreader) return false;
|
||
if (!usepri || !*usepri) return false;
|
||
if (!resconvert) return false;
|
||
return *resconvert;
|
||
#else
|
||
return false;
|
||
#endif
|
||
}
|
||
std::wstring pri_get_res (const std::wstring &resname)
|
||
{
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
if (resname.empty ()) return L"";
|
||
if (!pbreader) return L"";
|
||
return pbreader->resource (resname);
|
||
#else
|
||
return L"";
|
||
#endif
|
||
}
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
application (HPKGREAD hReader, prifilebundle *pri, bool *up, bool *resc):
|
||
hReader (hReader), pbreader (pri), usepri (up), resconvert (resc) {}
|
||
#endif
|
||
};
|
||
class applications
|
||
{
|
||
private:
|
||
HPKGREAD &hReader;
|
||
HAPPENUMERATOR hList = nullptr;
|
||
public:
|
||
applications (HPKGREAD &hReader): hReader (hReader)
|
||
{
|
||
hList = GetPackageApplications (hReader);
|
||
}
|
||
~applications ()
|
||
{
|
||
if (hList) DestroyPackageApplications (hList);
|
||
hList = nullptr;
|
||
}
|
||
size_t get (std::vector <application> &apps)
|
||
{
|
||
apps.clear ();
|
||
if (!hList) return 0;
|
||
HLIST_PVOID hMapList = ApplicationsToMap (hList);
|
||
deconstr endt ([&hMapList] {
|
||
if (hMapList) DestroyApplicationsMap (hMapList);
|
||
hMapList = nullptr;
|
||
});
|
||
if (!hMapList) return 0;
|
||
for (size_t i = 0; i < hMapList->dwSize; i ++)
|
||
{
|
||
HLIST_PVOID &hKeyValues = ((HLIST_PVOID *)hMapList->alpVoid) [i];
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
application app (hReader, pbreader, usepri, resconvert);
|
||
#else
|
||
application app;
|
||
#endif
|
||
for (size_t j = 0; j < hKeyValues->dwSize; j ++)
|
||
{
|
||
HPAIR_PVOID &hPair = ((HPAIR_PVOID *)hKeyValues->alpVoid) [j];
|
||
LPWSTR lpKey = (LPWSTR)hPair->lpKey;
|
||
LPWSTR lpValue = (LPWSTR)hPair->lpValue;
|
||
if (!lpKey || !*lpKey) continue;
|
||
app [lpKey] = lpValue ? lpValue : L"";
|
||
}
|
||
apps.push_back (app);
|
||
}
|
||
return apps.size ();
|
||
}
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
prifilebundle *pbreader = nullptr;
|
||
bool *usepri = nullptr;
|
||
bool *resconvert = nullptr;
|
||
applications (HPKGREAD &hReader, prifilebundle *pri, bool *up, bool *resc):
|
||
hReader (hReader), pbreader (pri), usepri (up), resconvert (resc) { hList = GetPackageApplications (hReader); }
|
||
#endif
|
||
};
|
||
class capabilities: public base_subitems
|
||
{
|
||
using base = base_subitems;
|
||
public:
|
||
using base::base;
|
||
size_t capabilities_name (std::vector <std::wstring> &output) const
|
||
{
|
||
output.clear ();
|
||
HLIST_PVOID hList = GetCapabilitiesList (hReader);
|
||
deconstr endt ([&hList] () {
|
||
if (hList) DestroyCapabilitiesList (hList);
|
||
hList = nullptr;
|
||
});
|
||
if (!hList) return 0;
|
||
for (size_t i = 0; i < hList->dwSize; i ++)
|
||
{
|
||
LPWSTR lpstr = (LPWSTR)hList->alpVoid [i];
|
||
if (!lpstr) continue;
|
||
output.push_back (lpstr);
|
||
}
|
||
return output.size ();
|
||
}
|
||
size_t device_capabilities (std::vector <std::wstring> &output) const
|
||
{
|
||
output.clear ();
|
||
HLIST_PVOID hList = GetDeviceCapabilitiesList (hReader);
|
||
deconstr endt ([&hList] () {
|
||
if (hList) DestroyDeviceCapabilitiesList (hList);
|
||
hList = nullptr;
|
||
});
|
||
if (!hList) return 0;
|
||
for (size_t i = 0; i < hList->dwSize; i ++)
|
||
{
|
||
LPWSTR lpstr = (LPWSTR)hList->alpVoid [i];
|
||
if (!lpstr) continue;
|
||
output.push_back (lpstr);
|
||
}
|
||
return output.size ();
|
||
}
|
||
};
|
||
struct dependency
|
||
{
|
||
std::wstring name, publisher;
|
||
VERSION vermin;
|
||
dependency (const std::wstring &name = L"", const std::wstring &pub = L"", const VERSION &ver = VERSION ()):
|
||
name (name), publisher (pub), vermin (ver) {}
|
||
};
|
||
class dependencies: public base_subitems
|
||
{
|
||
using base = base_subitems;
|
||
public:
|
||
using base::base;
|
||
size_t get (std::vector <dependency> &output) const
|
||
{
|
||
auto hList = GetDependencesInfoList (hReader);
|
||
deconstr rel ([&hList] () {
|
||
DestroyDependencesInfoList (hList);
|
||
});
|
||
if (!hList) return 0;
|
||
for (size_t i = 0; i < hList->dwSize; i ++)
|
||
{
|
||
DEPENDENCY_INFO &depinf = ((DEPENDENCY_INFO *)hList->aDepInfo) [i];
|
||
if (!depinf.lpName || !*depinf.lpName) continue;
|
||
output.push_back (dependency (depinf.lpName, depinf.lpPublisher ? depinf.lpPublisher : L"", depinf.verMin));
|
||
}
|
||
return output.size ();
|
||
}
|
||
};
|
||
class resources: public base_subitems
|
||
{
|
||
using base = base_subitems;
|
||
public:
|
||
using base::base;
|
||
size_t languages (std::vector <std::wstring> &langs) const
|
||
{
|
||
langs.clear ();
|
||
auto hList = GetResourcesLanguages (hReader);
|
||
deconstr rel ([&hList] () {
|
||
if (hList) DestroyResourcesLanguagesList (hList);
|
||
hList = nullptr;
|
||
});
|
||
if (!hList) return 0;
|
||
for (size_t i = 0; i < hList->dwSize; i ++)
|
||
{
|
||
LPWSTR lpstr = ((LPWSTR *)hList->alpVoid) [i];
|
||
if (lpstr && *lpstr) langs.push_back (std::wstring (lpstr));
|
||
}
|
||
return langs.size ();
|
||
}
|
||
size_t languages (std::vector <LCID> &langs) const
|
||
{
|
||
langs.clear ();
|
||
auto hList = GetResourcesLanguagesToLcid (hReader);
|
||
deconstr rel ([&hList] () {
|
||
if (hList) DestroyResourcesLanguagesLcidList (hList);
|
||
hList = nullptr;
|
||
});
|
||
if (!hList) return 0;
|
||
for (size_t i = 0; i < hList->dwSize; i ++)
|
||
{
|
||
if (hList->aLcid [i]) langs.push_back (hList->aLcid [i]);
|
||
}
|
||
return langs.size ();
|
||
}
|
||
size_t scales (std::vector <UINT32> &output) const
|
||
{
|
||
output.clear ();
|
||
auto hList = GetResourcesScales (hReader);
|
||
deconstr rel ([&hList] () {
|
||
if (hList) DestroyResourcesScalesList (hList);
|
||
});
|
||
if (!hList) return 0;
|
||
for (size_t i = 0; i < hList->dwSize; i ++)
|
||
{
|
||
UINT32 s = hList->aUI32 [i];
|
||
if (s) output.push_back (s);
|
||
}
|
||
return output.size ();
|
||
}
|
||
DWORD dx_feature_level () const { return GetResourcesDxFeatureLevels (hReader); }
|
||
// 向数组添加的是以 PKG_RESOURCES_DXFEATURE_* 前缀的常量
|
||
size_t dx_feature_level (std::vector <DWORD> &ret)
|
||
{
|
||
DWORD dx = dx_feature_level ();
|
||
if (dx & PKG_RESOURCES_DXFEATURE_LEVEL9) ret.push_back (PKG_RESOURCES_DXFEATURE_LEVEL9);
|
||
else if (dx & PKG_RESOURCES_DXFEATURE_LEVEL10) ret.push_back (PKG_RESOURCES_DXFEATURE_LEVEL10);
|
||
else if (dx & PKG_RESOURCES_DXFEATURE_LEVEL11) ret.push_back (PKG_RESOURCES_DXFEATURE_LEVEL11);
|
||
else if (dx & PKG_RESOURCES_DXFEATURE_LEVEL12) ret.push_back (PKG_RESOURCES_DXFEATURE_LEVEL12);
|
||
return ret.size ();
|
||
}
|
||
};
|
||
class prerequisites: public base_subitems
|
||
{
|
||
using base = base_subitems;
|
||
public:
|
||
using base::base;
|
||
VERSION get_version (const std::wstring &name) const
|
||
{
|
||
VERSION ver;
|
||
GetPackagePrerequisite (hReader, name.c_str (), &ver);
|
||
return ver;
|
||
}
|
||
VERSION os_min_version () const { return get_version (PKG_PREREQUISITE_OS_MIN_VERSION); }
|
||
VERSION os_max_version_tested () const { return get_version (PKG_PREREQUISITE_OS_MAX_VERSION_TESTED); }
|
||
std::wstring get_description (const std::wstring &name) const
|
||
{
|
||
LPWSTR lpstr = GetPackagePrerequistieSystemVersionName (hReader, name.c_str ());
|
||
deconstr relt ([&lpstr] () {
|
||
if (lpstr) free (lpstr);
|
||
lpstr = nullptr;
|
||
});
|
||
return lpstr ? lpstr : L"";
|
||
}
|
||
std::wstring os_min_version_description () const { return get_description (PKG_PREREQUISITE_OS_MIN_VERSION); }
|
||
std::wstring os_max_version_tested_description () const { return get_description (PKG_PREREQUISITE_OS_MAX_VERSION_TESTED); }
|
||
};
|
||
package_reader (): hReader (CreatePackageReader ()) {}
|
||
package_reader (const std::wstring &fpath): hReader (CreatePackageReader ())
|
||
{
|
||
file (fpath);
|
||
}
|
||
~package_reader ()
|
||
{
|
||
DestroyPackageReader (hReader);
|
||
hReader = nullptr;
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
pribundlereader.destroy ();
|
||
for (auto &it : prifilestreams) if (it != nullptr) DestroyAppxFileStream (it);
|
||
prifilestreams.clear ();
|
||
#endif
|
||
}
|
||
std::wstring file () const { return filepath; }
|
||
bool file (const std::wstring &path)
|
||
{
|
||
return LoadPackageFromFile (hReader, (filepath = path).c_str ());
|
||
}
|
||
// PKGTYPE_* 前缀常量
|
||
WORD package_type () const { return GetPackageType (hReader); }
|
||
bool valid () const { return hReader && IsPackageValid (hReader); }
|
||
// PKGROLE_* 前缀常量
|
||
WORD package_role () const { return GetPackageRole (hReader); }
|
||
identity get_identity () { return identity (hReader); }
|
||
properties get_properties ()
|
||
{
|
||
return properties (hReader
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
,
|
||
&pribundlereader,
|
||
&usepri,
|
||
&resswitch
|
||
#endif
|
||
);
|
||
}
|
||
applications get_applications ()
|
||
{
|
||
return applications (hReader
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
,
|
||
&pribundlereader,
|
||
&usepri,
|
||
&resswitch
|
||
#endif
|
||
);
|
||
}
|
||
capabilities get_capabilities () { return capabilities (hReader); }
|
||
dependencies get_dependencies () { return dependencies (hReader); }
|
||
resources get_resources () { return resources (hReader); }
|
||
prerequisites get_prerequisites () { return prerequisites (hReader); }
|
||
// 是否允许使用 PRI
|
||
bool use_pri () const
|
||
{
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
return usepri;
|
||
#else
|
||
return false;
|
||
#endif
|
||
}
|
||
// 是否允许使用 PRI
|
||
bool use_pri (bool value)
|
||
{
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
bool laststatus = usepri;
|
||
usepri = value;
|
||
if (laststatus ^ usepri) initpri ();
|
||
return usepri;
|
||
#else
|
||
return usepri = false;
|
||
#endif
|
||
}
|
||
// 是否自动从 PRI 中提取资源
|
||
bool enable_pri_convert () const { return resswitch; }
|
||
// 是否自动从 PRI 中提取资源
|
||
bool enable_pri_convert (bool value)
|
||
{
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
return resswitch = value;
|
||
#else
|
||
return resswitch = false;
|
||
#endif
|
||
}
|
||
};
|
||
class manifest_reader
|
||
{
|
||
private:
|
||
HPKGMANIFESTREAD hReader = nullptr;
|
||
std::wstring filepath = L"";
|
||
bool usepri = false;
|
||
bool resswitch = false;
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
prifile prireader;
|
||
#endif
|
||
std::wstring get_fileroot ()
|
||
{
|
||
std::vector <wchar_t> root (filepath.capacity ());
|
||
wcscpy (root.data (), filepath.c_str ());
|
||
PackageReaderGetFileRoot (root.data ());
|
||
return root.data ();
|
||
}
|
||
static std::wstring path_combine (const std::wstring &l, const std::wstring &r)
|
||
{
|
||
std::vector <wchar_t> buffer (l.length () + r.length () + 10);
|
||
PackageReaderCombinePath (l.c_str (), r.c_str (), buffer.data ());
|
||
return buffer.data ();
|
||
}
|
||
void initpri ()
|
||
{
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
prireader.destroy ();
|
||
switch (this->package_type ())
|
||
{
|
||
case PKGTYPE_APPX: {
|
||
prireader.create (path_combine (get_fileroot (), L"resources.pri"));
|
||
} break;
|
||
}
|
||
bool lastvalue = resswitch;
|
||
resswitch = false;
|
||
try
|
||
{
|
||
std::vector <std::wstring> resnames;
|
||
{
|
||
auto prop = get_properties ();
|
||
std::wstring temp = prop.description ();
|
||
if (IsMsResourcePrefix (temp.c_str ())) resnames.push_back (temp);
|
||
temp = prop.display_name ();
|
||
if (IsMsResourcePrefix (temp.c_str ())) resnames.push_back (temp);
|
||
temp = prop.publisher_display_name ();
|
||
if (IsMsResourcePrefix (temp.c_str ())) resnames.push_back (temp);
|
||
resnames.push_back (prop.logo ());
|
||
}
|
||
{
|
||
auto app = get_applications ();
|
||
std::vector <application> apps;
|
||
app.get (apps);
|
||
for (auto &it_map : apps)
|
||
{
|
||
for (auto &it_item : it_map)
|
||
{
|
||
if (std::find (g_filepathitems.begin (), g_filepathitems.end (), it_item.first) != g_filepathitems.end () && !it_item.second.empty ())
|
||
resnames.push_back (it_item.second);
|
||
else if (IsMsResourcePrefix (it_item.second.c_str ())) resnames.push_back (it_item.second);
|
||
}
|
||
}
|
||
}
|
||
prireader.add_search (resnames);
|
||
}
|
||
catch (const std::exception &e) {}
|
||
resswitch = lastvalue;
|
||
#endif
|
||
}
|
||
typedef struct deconstr
|
||
{
|
||
std::function <void ()> endtask = nullptr;
|
||
deconstr (std::function <void ()> pf): endtask (pf) {}
|
||
~deconstr () { if (endtask) endtask (); }
|
||
} destruct;
|
||
public:
|
||
class base_subitems
|
||
{
|
||
protected:
|
||
HPKGMANIFESTREAD &hReader;
|
||
public:
|
||
base_subitems (HPKGMANIFESTREAD &hReader): hReader (hReader) {}
|
||
};
|
||
class identity: public base_subitems
|
||
{
|
||
using base = base_subitems;
|
||
public:
|
||
using base::base;
|
||
std::wstring string_value (DWORD dwName) const
|
||
{
|
||
LPWSTR lpstr = nullptr;
|
||
deconstr rel ([&lpstr] () {
|
||
if (lpstr) free (lpstr);
|
||
lpstr = nullptr;
|
||
});
|
||
lpstr = GetManifestIdentityStringValue (hReader, dwName);
|
||
return lpstr ? lpstr : L"";
|
||
}
|
||
std::wstring name () const { return string_value (PKG_IDENTITY_NAME); }
|
||
std::wstring publisher () const { return string_value (PKG_IDENTITY_PUBLISHER); }
|
||
std::wstring package_family_name () const { return string_value (PKG_IDENTITY_PACKAGEFAMILYNAME); }
|
||
std::wstring package_full_name () const { return string_value (PKG_IDENTITY_PACKAGEFULLNAME); }
|
||
std::wstring resource_id () const { return string_value (PKG_IDENTITY_RESOURCEID); }
|
||
VERSION version (bool read_subpkg_ver = false) const { VERSION ver; GetManifestIdentityVersion (hReader, &ver); return ver; }
|
||
DWORD architecture () const { DWORD dw = 0; GetManifestIdentityArchitecture (hReader, &dw); return dw; }
|
||
};
|
||
class properties: public base_subitems
|
||
{
|
||
using base = base_subitems;
|
||
std::wstring root = L"";
|
||
public:
|
||
using base::base;
|
||
std::wstring string_value (const std::wstring &swName) const
|
||
{
|
||
LPWSTR lpstr = nullptr;
|
||
deconstr rel ([&lpstr] () {
|
||
if (lpstr) free (lpstr);
|
||
lpstr = nullptr;
|
||
});
|
||
lpstr = GetManifestPropertiesStringValue (hReader, swName.c_str ());
|
||
return lpstr ? lpstr : L"";
|
||
}
|
||
bool bool_value (const std::wstring &swName, bool bRetWhenFailed = false) const
|
||
{
|
||
BOOL ret = FALSE;
|
||
HRESULT hr = GetManifestPropertiesBoolValue (hReader, swName.c_str (), &ret);
|
||
if (FAILED (hr)) return bRetWhenFailed;
|
||
else return ret != FALSE;
|
||
}
|
||
std::wstring display_name (bool toprires = true)
|
||
{
|
||
std::wstring ret = string_value (PKG_PROPERTIES_DISPLAYNAME);
|
||
if (!toprires) return ret;
|
||
if (!enable_pri ()) return ret;
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
else
|
||
{
|
||
if (!IsMsResourcePrefix (ret.c_str ())) return ret;
|
||
std::wstring privalue = pri_get_res (ret);
|
||
if (privalue.empty ()) return ret;
|
||
return privalue;
|
||
}
|
||
#endif
|
||
return ret;
|
||
}
|
||
std::wstring publisher_display_name (bool toprires = true)
|
||
{
|
||
std::wstring ret = string_value (PKG_PROPERTIES_PUBLISHER);
|
||
if (!toprires) return ret;
|
||
if (!enable_pri ()) return ret;
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
else
|
||
{
|
||
if (!IsMsResourcePrefix (ret.c_str ())) return ret;
|
||
std::wstring privalue = pri_get_res (ret);
|
||
if (privalue.empty ()) return ret;
|
||
return privalue;
|
||
}
|
||
#endif
|
||
return ret;
|
||
}
|
||
std::wstring description (bool toprires = true)
|
||
{
|
||
std::wstring ret = string_value (PKG_PROPERTIES_DESCRIPTION);
|
||
if (!toprires) return ret;
|
||
if (!enable_pri ()) return ret;
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
else
|
||
{
|
||
if (!IsMsResourcePrefix (ret.c_str ())) return ret;
|
||
std::wstring privalue = pri_get_res (ret);
|
||
if (privalue.empty ()) return ret;
|
||
return privalue;
|
||
}
|
||
#endif
|
||
return ret;
|
||
}
|
||
std::wstring logo (bool toprires = true)
|
||
{
|
||
std::wstring ret = string_value (PKG_PROPERTIES_LOGO);
|
||
if (!toprires) return ret;
|
||
if (!enable_pri ()) return ret;
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
else
|
||
{
|
||
std::wstring privalue = pri_get_res (ret);
|
||
if (privalue.empty ()) return ret;
|
||
return privalue;
|
||
}
|
||
#endif
|
||
return ret;
|
||
}
|
||
std::wstring logo_base64 ()
|
||
{
|
||
switch (GetManifestType (hReader))
|
||
{
|
||
case PKGTYPE_APPX: {
|
||
auto path = path_combine (root, logo ());
|
||
HANDLE pic = PackageReaderGetFileStream (path.c_str ());
|
||
destruct relp ([&pic] () {
|
||
if (pic) PackageReaderDestroyFileStream (pic);
|
||
pic = nullptr;
|
||
});
|
||
LPWSTR lpstr = nullptr;
|
||
destruct rel ([&lpstr] () {
|
||
if (lpstr) free (lpstr);
|
||
lpstr = nullptr;
|
||
});
|
||
lpstr = StreamToBase64W (pic, nullptr, 0, nullptr);
|
||
return lpstr ? lpstr : L"";
|
||
} break;
|
||
}
|
||
return L"";
|
||
}
|
||
bool framework () const { return bool_value (PKG_PROPERTIES_FRAMEWORD); }
|
||
bool resource_package () const { return bool_value (PKG_PROPERTIES_IS_RESOURCE); }
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
prifile *pbreader = nullptr;
|
||
bool *usepri = nullptr;
|
||
bool *resconvert = nullptr;
|
||
#endif
|
||
bool enable_pri () const
|
||
{
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
if (!pbreader) return false;
|
||
if (!usepri || !*usepri) return false;
|
||
if (!resconvert) return false;
|
||
return *resconvert;
|
||
#else
|
||
return false;
|
||
#endif
|
||
}
|
||
std::wstring pri_get_res (const std::wstring &resname)
|
||
{
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
if (resname.empty ()) return L"";
|
||
if (!pbreader) return L"";
|
||
return pbreader->resource (resname);
|
||
#else
|
||
return L"";
|
||
#endif
|
||
}
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
properties (HPKGMANIFESTREAD &hReader, prifile *pri, bool *up, bool *resc, const std::wstring &pathroot):
|
||
base (hReader), pbreader (pri), usepri (up), resconvert (resc), root (pathroot) {}
|
||
#endif
|
||
};
|
||
class application: public std::map <std::wstring, std::wstring>
|
||
{
|
||
using base = std::map <std::wstring, std::wstring>;
|
||
std::wstring root = L"";
|
||
public:
|
||
using base::base;
|
||
application () = default;
|
||
std::wstring user_model_id () { return this->at (L"AppUserModelID"); }
|
||
friend bool operator == (application &a1, application &a2) { return !_wcsicmp (a1.user_model_id ().c_str (), a2.user_model_id ().c_str ()); }
|
||
friend bool operator != (application &a1, application &a2) { return _wcsicmp (a1.user_model_id ().c_str (), a2.user_model_id ().c_str ()); }
|
||
explicit operator bool () { return this->user_model_id ().empty (); }
|
||
std::wstring &operator [] (const std::wstring &key)
|
||
{
|
||
auto it = this->find (key);
|
||
if (it == this->end ())
|
||
{
|
||
it = this->insert (std::make_pair (key, L"")).first;
|
||
}
|
||
if (!enable_pri ()) return it->second;
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
if (IsMsResourcePrefix (it->second.c_str ()))
|
||
{
|
||
std::wstring privalue = pri_get_res (it->second);
|
||
if (!privalue.empty ()) return privalue;
|
||
return it->second;
|
||
}
|
||
else if (std::find (g_filepathitems.begin (), g_filepathitems.end (), it->first) != g_filepathitems.end () && !it->second.empty ())
|
||
{
|
||
std::wstring privalue = pri_get_res (it->second);
|
||
if (!privalue.empty ()) return privalue;
|
||
return it->second;
|
||
}
|
||
#endif
|
||
return it->second;
|
||
}
|
||
typename base::iterator find_case_insensitive (const std::wstring &key)
|
||
{
|
||
for (auto it = this->begin (); it != this->end (); ++it)
|
||
{
|
||
if (_wcsicmp (it->first.c_str (), key.c_str ()) == 0)
|
||
return it;
|
||
}
|
||
return this->end ();
|
||
}
|
||
typename base::const_iterator find_case_insensitive (const std::wstring &key) const
|
||
{
|
||
for (auto it = this->begin (); it != this->end (); ++ it)
|
||
{
|
||
if (_wcsicmp (it->first.c_str (), key.c_str ()) == 0)
|
||
return it;
|
||
}
|
||
return this->end ();
|
||
}
|
||
std::wstring at (const std::wstring &key)
|
||
{
|
||
auto it = this->find_case_insensitive (key);
|
||
if (it == this->end ()) throw std::out_of_range ("application::at: key not found");
|
||
if (!enable_pri ()) return it->second;
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
if (IsMsResourcePrefix (it->second.c_str ()))
|
||
{
|
||
std::wstring privalue = pri_get_res (it->second);
|
||
if (!privalue.empty ()) return privalue;
|
||
}
|
||
#endif
|
||
return it->second;
|
||
}
|
||
std::wstring newat (const std::wstring &key, bool to_pri_string = true)
|
||
{
|
||
auto it = this->find (key);
|
||
if (it == this->end ())
|
||
{
|
||
it = this->insert (std::make_pair (key, L"")).first;
|
||
}
|
||
if (!enable_pri () && to_pri_string) return it->second;
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
if (IsMsResourcePrefix (it->second.c_str ()))
|
||
{
|
||
std::wstring privalue = pri_get_res (it->second);
|
||
if (!privalue.empty ()) return privalue;
|
||
return it->second;
|
||
}
|
||
else if (std::find (g_filepathitems.begin (), g_filepathitems.end (), it->first) != g_filepathitems.end () && !it->second.empty ())
|
||
{
|
||
std::wstring privalue = pri_get_res (it->second);
|
||
if (!privalue.empty ()) return privalue;
|
||
return it->second;
|
||
}
|
||
#endif
|
||
return it->second;
|
||
}
|
||
// 仅支持文件
|
||
std::wstring newat_base64 (const std::wstring &key)
|
||
{
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
std::wstring value = newat (key);
|
||
if (std::find (g_filepathitems.begin (), g_filepathitems.end (), key) != g_filepathitems.end () && !value.empty ())
|
||
{
|
||
switch (GetManifestType (hReader))
|
||
{
|
||
case PKGTYPE_APPX: {
|
||
auto filepath = path_combine (root, value);
|
||
HANDLE pic = PackageReaderGetFileStream (filepath.c_str ());
|
||
destruct relp ([&pic] () {
|
||
if (pic) PackageReaderDestroyFileStream (pic);
|
||
pic = nullptr;
|
||
});
|
||
LPWSTR lpstr = nullptr;
|
||
destruct rel ([&lpstr] () {
|
||
if (lpstr) free (lpstr);
|
||
lpstr = nullptr;
|
||
});
|
||
lpstr = StreamToBase64W (pic, nullptr, 0, nullptr);
|
||
return lpstr ? lpstr : L"";
|
||
} break;
|
||
}
|
||
return L"";
|
||
}
|
||
else return L"";
|
||
#else
|
||
return L"";
|
||
#endif
|
||
}
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
HPKGMANIFESTREAD hReader = nullptr;
|
||
prifile *pbreader = nullptr;
|
||
bool *usepri = nullptr;
|
||
bool *resconvert = nullptr;
|
||
#endif
|
||
bool enable_pri () const
|
||
{
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
if (!pbreader) return false;
|
||
if (!usepri || !*usepri) return false;
|
||
if (!resconvert) return false;
|
||
return *resconvert;
|
||
#else
|
||
return false;
|
||
#endif
|
||
}
|
||
std::wstring pri_get_res (const std::wstring &resname)
|
||
{
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
if (resname.empty ()) return L"";
|
||
if (!pbreader) return L"";
|
||
return pbreader->resource (resname);
|
||
#else
|
||
return L"";
|
||
#endif
|
||
}
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
application (HPKGMANIFESTREAD hReader, prifile *pri, bool *up, bool *resc, const std::wstring &pathroot):
|
||
hReader (hReader), pbreader (pri), usepri (up), resconvert (resc), root (pathroot) {}
|
||
#endif
|
||
};
|
||
class applications
|
||
{
|
||
private:
|
||
HPKGMANIFESTREAD &hReader;
|
||
HAPPENUMERATOR hList = nullptr;
|
||
std::wstring root = L"";
|
||
public:
|
||
applications (HPKGMANIFESTREAD &hReader): hReader (hReader)
|
||
{
|
||
hList = GetManifestApplications (hReader);
|
||
}
|
||
~applications ()
|
||
{
|
||
if (hList) DestroyPackageApplications (hList);
|
||
hList = nullptr;
|
||
}
|
||
size_t get (std::vector <application> &apps)
|
||
{
|
||
apps.clear ();
|
||
if (!hList) return 0;
|
||
HLIST_PVOID hMapList = ApplicationsToMap (hList);
|
||
deconstr endt ([&hMapList] {
|
||
if (hMapList) DestroyApplicationsMap (hMapList);
|
||
hMapList = nullptr;
|
||
});
|
||
if (!hMapList) return 0;
|
||
for (size_t i = 0; i < hMapList->dwSize; i ++)
|
||
{
|
||
HLIST_PVOID &hKeyValues = ((HLIST_PVOID *)hMapList->alpVoid) [i];
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
application app (hReader, pbreader, usepri, resconvert, root);
|
||
#else
|
||
application app;
|
||
#endif
|
||
for (size_t j = 0; j < hKeyValues->dwSize; j ++)
|
||
{
|
||
HPAIR_PVOID &hPair = ((HPAIR_PVOID *)hKeyValues->alpVoid) [j];
|
||
LPWSTR lpKey = (LPWSTR)hPair->lpKey;
|
||
LPWSTR lpValue = (LPWSTR)hPair->lpValue;
|
||
if (!lpKey || !*lpKey) continue;
|
||
app [lpKey] = lpValue ? lpValue : L"";
|
||
}
|
||
apps.push_back (app);
|
||
}
|
||
return apps.size ();
|
||
}
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
prifile *pbreader = nullptr;
|
||
bool *usepri = nullptr;
|
||
bool *resconvert = nullptr;
|
||
applications (HPKGMANIFESTREAD &hReader, prifile *pri, bool *up, bool *resc, const std::wstring &pathroot):
|
||
hReader (hReader), pbreader (pri), usepri (up), resconvert (resc), root (pathroot) { hList = GetManifestApplications (hReader); }
|
||
#endif
|
||
};
|
||
class capabilities: public base_subitems
|
||
{
|
||
using base = base_subitems;
|
||
public:
|
||
using base::base;
|
||
size_t capabilities_name (std::vector <std::wstring> &output) const
|
||
{
|
||
output.clear ();
|
||
HLIST_PVOID hList = GetManifestCapabilitiesList (hReader);
|
||
deconstr endt ([&hList] () {
|
||
if (hList) DestroyCapabilitiesList (hList);
|
||
hList = nullptr;
|
||
});
|
||
if (!hList) return 0;
|
||
for (size_t i = 0; i < hList->dwSize; i ++)
|
||
{
|
||
LPWSTR lpstr = (LPWSTR)hList->alpVoid [i];
|
||
if (!lpstr) continue;
|
||
output.push_back (lpstr);
|
||
}
|
||
return output.size ();
|
||
}
|
||
size_t device_capabilities (std::vector <std::wstring> &output) const
|
||
{
|
||
output.clear ();
|
||
HLIST_PVOID hList = GetManifestDeviceCapabilitiesList (hReader);
|
||
deconstr endt ([&hList] () {
|
||
if (hList) DestroyDeviceCapabilitiesList (hList);
|
||
hList = nullptr;
|
||
});
|
||
if (!hList) return 0;
|
||
for (size_t i = 0; i < hList->dwSize; i ++)
|
||
{
|
||
LPWSTR lpstr = (LPWSTR)hList->alpVoid [i];
|
||
if (!lpstr) continue;
|
||
output.push_back (lpstr);
|
||
}
|
||
return output.size ();
|
||
}
|
||
};
|
||
struct dependency
|
||
{
|
||
std::wstring name, publisher;
|
||
VERSION vermin;
|
||
dependency (const std::wstring &name = L"", const std::wstring &pub = L"", const VERSION &ver = VERSION ()):
|
||
name (name), publisher (pub), vermin (ver) {}
|
||
};
|
||
class dependencies: public base_subitems
|
||
{
|
||
using base = base_subitems;
|
||
public:
|
||
using base::base;
|
||
size_t get (std::vector <dependency> &output) const
|
||
{
|
||
auto hList = GetManifestDependencesInfoList (hReader);
|
||
deconstr rel ([&hList] () {
|
||
DestroyDependencesInfoList (hList);
|
||
});
|
||
if (!hList) return 0;
|
||
for (size_t i = 0; i < hList->dwSize; i ++)
|
||
{
|
||
DEPENDENCY_INFO &depinf = ((DEPENDENCY_INFO *)hList->aDepInfo) [i];
|
||
if (!depinf.lpName || !*depinf.lpName) continue;
|
||
output.push_back (dependency (depinf.lpName, depinf.lpPublisher ? depinf.lpPublisher : L"", depinf.verMin));
|
||
}
|
||
return output.size ();
|
||
}
|
||
};
|
||
class resources: public base_subitems
|
||
{
|
||
using base = base_subitems;
|
||
public:
|
||
using base::base;
|
||
size_t languages (std::vector <std::wstring> &langs) const
|
||
{
|
||
langs.clear ();
|
||
auto hList = GetManifestResourcesLanguages (hReader);
|
||
deconstr rel ([&hList] () {
|
||
if (hList) DestroyResourcesLanguagesList (hList);
|
||
hList = nullptr;
|
||
});
|
||
if (!hList) return 0;
|
||
for (size_t i = 0; i < hList->dwSize; i ++)
|
||
{
|
||
LPWSTR lpstr = ((LPWSTR *)hList->alpVoid) [i];
|
||
if (lpstr && *lpstr) langs.push_back (std::wstring (lpstr));
|
||
}
|
||
return langs.size ();
|
||
}
|
||
size_t languages (std::vector <LCID> &langs) const
|
||
{
|
||
langs.clear ();
|
||
auto hList = GetManifestResourcesLanguagesToLcid (hReader);
|
||
deconstr rel ([&hList] () {
|
||
if (hList) DestroyResourcesLanguagesLcidList (hList);
|
||
hList = nullptr;
|
||
});
|
||
if (!hList) return 0;
|
||
for (size_t i = 0; i < hList->dwSize; i ++)
|
||
{
|
||
if (hList->aLcid [i]) langs.push_back (hList->aLcid [i]);
|
||
}
|
||
return langs.size ();
|
||
}
|
||
size_t scales (std::vector <UINT32> &output) const
|
||
{
|
||
output.clear ();
|
||
auto hList = GetManifestResourcesScales (hReader);
|
||
deconstr rel ([&hList] () {
|
||
if (hList) DestroyResourcesScalesList (hList);
|
||
});
|
||
if (!hList) return 0;
|
||
for (size_t i = 0; i < hList->dwSize; i ++)
|
||
{
|
||
UINT32 s = hList->aUI32 [i];
|
||
if (s) output.push_back (s);
|
||
}
|
||
return output.size ();
|
||
}
|
||
DWORD dx_feature_level () const { return GetManifestResourcesDxFeatureLevels (hReader); }
|
||
// 向数组添加的是以 PKG_RESOURCES_DXFEATURE_* 前缀的常量
|
||
size_t dx_feature_level (std::vector <DWORD> &ret)
|
||
{
|
||
DWORD dx = dx_feature_level ();
|
||
if (dx & PKG_RESOURCES_DXFEATURE_LEVEL9) ret.push_back (PKG_RESOURCES_DXFEATURE_LEVEL9);
|
||
else if (dx & PKG_RESOURCES_DXFEATURE_LEVEL10) ret.push_back (PKG_RESOURCES_DXFEATURE_LEVEL10);
|
||
else if (dx & PKG_RESOURCES_DXFEATURE_LEVEL11) ret.push_back (PKG_RESOURCES_DXFEATURE_LEVEL11);
|
||
else if (dx & PKG_RESOURCES_DXFEATURE_LEVEL12) ret.push_back (PKG_RESOURCES_DXFEATURE_LEVEL12);
|
||
return ret.size ();
|
||
}
|
||
};
|
||
class prerequisites: public base_subitems
|
||
{
|
||
using base = base_subitems;
|
||
public:
|
||
using base::base;
|
||
VERSION get_version (const std::wstring &name) const
|
||
{
|
||
VERSION ver;
|
||
GetManifestPrerequisite (hReader, name.c_str (), &ver);
|
||
return ver;
|
||
}
|
||
VERSION os_min_version () const { return get_version (PKG_PREREQUISITE_OS_MIN_VERSION); }
|
||
VERSION os_max_version_tested () const { return get_version (PKG_PREREQUISITE_OS_MAX_VERSION_TESTED); }
|
||
std::wstring get_description (const std::wstring &name) const
|
||
{
|
||
LPWSTR lpstr = GetManifestPrerequistieSystemVersionName (hReader, name.c_str ());
|
||
deconstr relt ([&lpstr] () {
|
||
if (lpstr) free (lpstr);
|
||
lpstr = nullptr;
|
||
});
|
||
return lpstr ? lpstr : L"";
|
||
}
|
||
std::wstring os_min_version_description () const { return get_description (PKG_PREREQUISITE_OS_MIN_VERSION); }
|
||
std::wstring os_max_version_tested_description () const { return get_description (PKG_PREREQUISITE_OS_MAX_VERSION_TESTED); }
|
||
};
|
||
manifest_reader (): hReader (CreateManifestReader ()) {}
|
||
manifest_reader (const std::wstring &fpath): hReader (CreateManifestReader ())
|
||
{
|
||
file (fpath);
|
||
}
|
||
~manifest_reader ()
|
||
{
|
||
DestroyManifestReader (hReader);
|
||
hReader = nullptr;
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
prireader.destroy ();
|
||
#endif
|
||
}
|
||
std::wstring file () const { return filepath; }
|
||
bool file (const std::wstring &path)
|
||
{
|
||
return LoadManifestFromFile (hReader, (filepath = path).c_str ());
|
||
}
|
||
// PKGTYPE_* 前缀常量
|
||
WORD package_type () const { return GetManifestType (hReader); }
|
||
bool valid () const { return hReader && IsManifestValid (hReader); }
|
||
// PKGROLE_* 前缀常量
|
||
WORD package_role () const { return GetManifestRole (hReader); }
|
||
identity get_identity () { return identity (hReader); }
|
||
properties get_properties ()
|
||
{
|
||
return properties (hReader
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
,
|
||
&prireader,
|
||
&usepri,
|
||
&resswitch,
|
||
get_fileroot ()
|
||
#endif
|
||
);
|
||
}
|
||
applications get_applications ()
|
||
{
|
||
return applications (hReader
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
,
|
||
&prireader,
|
||
&usepri,
|
||
&resswitch,
|
||
get_fileroot ()
|
||
#endif
|
||
);
|
||
}
|
||
capabilities get_capabilities () { return capabilities (hReader); }
|
||
dependencies get_dependencies () { return dependencies (hReader); }
|
||
resources get_resources () { return resources (hReader); }
|
||
prerequisites get_prerequisites () { return prerequisites (hReader); }
|
||
// 是否允许使用 PRI
|
||
bool use_pri () const
|
||
{
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
return usepri;
|
||
#else
|
||
return false;
|
||
#endif
|
||
}
|
||
// 是否允许使用 PRI
|
||
bool use_pri (bool value)
|
||
{
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
bool laststatus = usepri;
|
||
usepri = value;
|
||
if (laststatus ^ usepri) initpri ();
|
||
return usepri;
|
||
#else
|
||
return usepri = false;
|
||
#endif
|
||
}
|
||
// 是否自动从 PRI 中提取资源
|
||
bool enable_pri_convert () const { return resswitch; }
|
||
// 是否自动从 PRI 中提取资源
|
||
bool enable_pri_convert (bool value)
|
||
{
|
||
#ifdef _PRI_READER_CLI_HEADER_
|
||
return resswitch = value;
|
||
#else
|
||
return resswitch = false;
|
||
#endif
|
||
}
|
||
};
|
||
#endif
|
||
|
||
#endif
|