// 下列 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_ #ifdef 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 #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_) #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) && !defined (PKGREAD_EXPORTS) #include #include #include #include #include #include class package_reader { private: HPKGREAD hReader = nullptr; std::wstring filepath = L""; struct deconstr { std::function endtask = nullptr; deconstr (std::function pf): endtask (pf) {} ~deconstr () { if (endtask) endtask (); } }; 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 () const { return string_value (PKG_PROPERTIES_DISPLAYNAME); } std::wstring publisher_display_name () const { return string_value (PKG_PROPERTIES_PUBLISHER); } std::wstring description () const { return string_value (PKG_PROPERTIES_DESCRIPTION); } std::wstring logo () const { return string_value (PKG_PROPERTIES_LOGO); } bool framework () const { return bool_value (PKG_PROPERTIES_FRAMEWORD); } bool resource_package () const { return bool_value (PKG_PROPERTIES_IS_RESOURCE); } }; class application: public std::map { using base = std::map ; public: using base::base; std::wstring user_model_id () const { return this->find (L"AppUserModelID")->second; } friend bool operator == (const application &a1, const application &a2) { return !_wcsicmp (a1.user_model_id ().c_str (), a2.user_model_id ().c_str ()); } friend bool operator != (const application &a1, const application &a2) { return _wcsicmp (a1.user_model_id ().c_str (), a2.user_model_id ().c_str ()); } explicit operator bool () const { 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; } 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 (); } }; 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 &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]; application app; 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 (); } }; class capabilities: public base_subitems { using base = base_subitems; public: using base::base; size_t capabilities_name (std::vector &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 &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 &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 &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 &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 &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 &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); } }; package_reader (): hReader (CreatePackageReader ()) {} package_reader (const std::wstring &fpath): hReader (CreatePackageReader ()) { file (fpath); } ~package_reader () { DestroyPackageReader (hReader); hReader = nullptr; } 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); } applications get_applications () { return applications (hReader); } capabilities get_capabilities () { return capabilities (hReader); } dependencies get_dependencies () { return dependencies (hReader); } resources get_resources () { return resources (hReader); } prerequisites get_prerequisites () { return prerequisites (hReader); } }; #endif #endif