Updated manager and added appx manifest reader.

This commit is contained in:
Bruce
2026-01-24 22:06:55 +08:00
parent 75cb72964d
commit 503ece1c64
60 changed files with 4980 additions and 3819 deletions

View File

@@ -1213,4 +1213,544 @@ LPWSTR GetPackageCapabilityDisplayName (LPCWSTR lpCapabilityName)
std::wstring ret = GetCapabilityDisplayName (capname);
if (IsNormalizeStringEmpty (ret)) return nullptr;
else return _wcsdup (ret.c_str ());
}
}
void PackageReaderFreeString (LPWSTR lpStrFromThisDll)
{
if (!lpStrFromThisDll) return;
free (lpStrFromThisDll);
}
// ========== 以下是对清单文件的读取 ==========
#define ToHandleMRead(_cpp_ptr_) reinterpret_cast <HPKGMANIFESTREAD> (_cpp_ptr_)
#define ToPtrManifest(_cpp_ptr_) reinterpret_cast <manifest *> (_cpp_ptr_)
HPKGMANIFESTREAD CreateManifestReader () { return ToHandleMRead (new manifest ()); }
BOOL LoadManifestFromFile (_In_ HPKGMANIFESTREAD hReader, _In_ LPCWSTR lpFilePath)
{
auto ptr = ToPtrManifest (hReader);
if (!ptr) return false;
return ptr->create (lpFilePath);
}
void DestroyManifestReader (_In_ HPKGMANIFESTREAD hReader)
{
auto ptr = ToPtrManifest (hReader);
if (!ptr) return;
return delete ptr;
}
WORD GetManifestType (_In_ HPKGMANIFESTREAD hReader)
{
auto ptr = ToPtrManifest (hReader);
if (!ptr) return PKGTYPE_UNKNOWN;
switch (ptr->type ())
{
case PackageType::unknown: return PKGTYPE_UNKNOWN;
case PackageType::single: return PKGTYPE_APPX;
case PackageType::bundle: return PKGTYPE_BUNDLE;
}
return PKGTYPE_UNKNOWN;
}
BOOL IsManifestValid (_In_ HPKGMANIFESTREAD hReader)
{
auto ptr = ToPtrManifest (hReader);
if (!ptr) return false;
return ptr->valid ();
}
WORD GetManifestRole (_In_ HPKGMANIFESTREAD hReader)
{
auto ptr = ToPtrManifest (hReader);
if (!ptr) return PKGROLE_UNKNOWN;
switch (ptr->type ())
{
case PackageType::unknown: return PKGROLE_UNKNOWN;
case PackageType::bundle: return PKGROLE_APPLICATION;
case PackageType::single: {
auto ar = ptr->appx_reader ();
switch (ar.package_role ())
{
case PackageRole::unknown: return PKGROLE_UNKNOWN;
case PackageRole::application: return PKGROLE_APPLICATION;
case PackageRole::framework: return PKGROLE_FRAMEWORK;
case PackageRole::resource: return PKGROLE_RESOURCE;
}
} break;
}
return PKGROLE_UNKNOWN;
}
// Identity
LPWSTR GetManifestIdentityStringValue (_In_ HPKGMANIFESTREAD hReader, _In_ DWORD dwName)
{
auto ptr = ToPtrManifest (hReader);
if (!ptr) return nullptr;
switch (ptr->type ())
{
case PackageType::single: {
auto reader = ptr->appx_reader ();
auto id = reader.identity ();
switch (LOWORD (dwName))
{
case PKG_IDENTITY_NAME: return _wcsdup (id.name ().c_str ());
case PKG_IDENTITY_PUBLISHER: return _wcsdup (id.publisher ().c_str ());
case PKG_IDENTITY_PACKAGEFAMILYNAME: return _wcsdup (id.package_family_name ().c_str ());
case PKG_IDENTITY_PACKAGEFULLNAME: return _wcsdup (id.package_full_name ().c_str ());
case PKG_IDENTITY_RESOURCEID: return _wcsdup (id.resource_id ().c_str ());
}
} break;
case PackageType::bundle: {
auto reader = ptr->bundle_reader ();
auto id = reader.identity ();
{
switch (LOWORD (dwName))
{
case PKG_IDENTITY_NAME: return _wcsdup (id.name ().c_str ());
case PKG_IDENTITY_PUBLISHER: return _wcsdup (id.publisher ().c_str ());
case PKG_IDENTITY_PACKAGEFAMILYNAME: return _wcsdup (id.package_family_name ().c_str ());
case PKG_IDENTITY_PACKAGEFULLNAME: return _wcsdup (id.package_full_name ().c_str ());
case PKG_IDENTITY_RESOURCEID: return _wcsdup (id.resource_id ().c_str ());
}
}
} break;
}
return nullptr;
}
BOOL GetManifestIdentityVersion (_In_ HPKGMANIFESTREAD hReader, _Out_ VERSION *pVersion)
{
auto ptr = ToPtrManifest (hReader);
if (!ptr) return FALSE;
if (!pVersion) return FALSE;
switch (ptr->type ())
{
case PackageType::single: {
auto reader = ptr->appx_reader ();
auto id = reader.identity ();
auto ver = id.version ();
*pVersion = VersionClassToStruct (ver);
return !ver.empty ();
} break;
case PackageType::bundle: {
auto reader = ptr->bundle_reader ();
auto id = reader.identity ();
{
auto ver = id.version ();
*pVersion = VersionClassToStruct (ver);
return !ver.empty ();
}
} break;
}
return FALSE;
}
BOOL GetManifestIdentityArchitecture (_In_ HPKGMANIFESTREAD hReader, _Out_ DWORD *pdwArchi)
{
auto ptr = ToPtrManifest (hReader);
if (!ptr) return FALSE;
if (!pdwArchi) return FALSE;
switch (ptr->type ())
{
case PackageType::single: {
auto reader = ptr->appx_reader ();
auto id = reader.identity ();
auto archi = id.architecture ();
DWORD ret = 0;
switch (archi)
{
case APPX_PACKAGE_ARCHITECTURE::APPX_PACKAGE_ARCHITECTURE_X86:
ret = PKG_ARCHITECTURE_X86; break;
case APPX_PACKAGE_ARCHITECTURE::APPX_PACKAGE_ARCHITECTURE_ARM:
ret = PKG_ARCHITECTURE_ARM; break;
case APPX_PACKAGE_ARCHITECTURE::APPX_PACKAGE_ARCHITECTURE_X64:
ret = PKG_ARCHITECTURE_X64; break;
case APPX_PACKAGE_ARCHITECTURE::APPX_PACKAGE_ARCHITECTURE_NEUTRAL:
ret = PKG_ARCHITECTURE_NEUTRAL; break;
case (APPX_PACKAGE_ARCHITECTURE)12: // ARM64
ret = PKG_ARCHITECTURE_ARM64; break;
}
*pdwArchi = ret;
return ret != PKG_ARCHITECTURE_UNKNOWN;
} break;
case PackageType::bundle: {
auto reader = ptr->bundle_reader ();
auto ids = reader.package_id_items ();
std::vector <appx_info::appx_iditem> apps;
ids.application_packages (apps);
DWORD ret = 0;
for (auto &it : apps)
{
auto id = it.identity ();
auto archi = id.architecture ();
switch (archi)
{
case APPX_PACKAGE_ARCHITECTURE::APPX_PACKAGE_ARCHITECTURE_X86:
ret |= PKG_ARCHITECTURE_X86; break;
case APPX_PACKAGE_ARCHITECTURE::APPX_PACKAGE_ARCHITECTURE_ARM:
ret |= PKG_ARCHITECTURE_ARM; break;
case APPX_PACKAGE_ARCHITECTURE::APPX_PACKAGE_ARCHITECTURE_X64:
ret |= PKG_ARCHITECTURE_X64; break;
case APPX_PACKAGE_ARCHITECTURE::APPX_PACKAGE_ARCHITECTURE_NEUTRAL:
ret |= PKG_ARCHITECTURE_NEUTRAL; break;
case (APPX_PACKAGE_ARCHITECTURE)12: // ARM64
ret |= PKG_ARCHITECTURE_ARM64; break;
}
}
*pdwArchi = ret;
return ret != PKG_ARCHITECTURE_UNKNOWN;
} break;
}
return FALSE;
}
// Properties
LPWSTR GetManifestPropertiesStringValue (_In_ HPKGMANIFESTREAD hReader, _In_ LPCWSTR lpName)
{
auto ptr = ToPtrManifest (hReader);
if (!ptr) return nullptr;
switch (ptr->type ())
{
case PackageType::single: {
auto reader = ptr->appx_reader ();
auto prop = reader.properties ();
return _wcsdup (prop.string_value (lpName ? lpName : L"").c_str ());
} break;
}
return nullptr;
}
HRESULT GetManifestPropertiesBoolValue (_In_ HPKGMANIFESTREAD hReader, _In_ LPCWSTR lpName, _Outptr_ BOOL *pRet)
{
auto ptr = ToPtrManifest (hReader);
if (!ptr) return E_INVALIDARG;
if (!pRet) return E_INVALIDARG;
*pRet = FALSE;
switch (ptr->type ())
{
case PackageType::single: {
auto reader = ptr->appx_reader ();
IAppxManifestReader *m = reader.manifest ();
if (!m) return E_FAIL;
CComPtr <IAppxManifestProperties> p;
HRESULT hr = m->GetProperties (&p);
if (FAILED (hr)) return hr;
return p->GetBoolValue (lpName, pRet);
} break;
}
return E_FAIL;
}
// Applications
BOOL AddManifestApplicationItemGetName (_In_ LPCWSTR lpName)
{
if (std::wnstring (lpName ? lpName : L"").empty ()) return FALSE;
return PushApplicationAttributeItem (lpName);
}
BOOL RemoveManifestApplicationItemGetName (_In_ LPCWSTR lpName)
{
if (std::wnstring (lpName ? lpName : L"").empty ()) return FALSE;
return RemoveApplicationAttributeItem (lpName);
}
HAPPENUMERATOR GetManifestApplications (_In_ HPKGMANIFESTREAD hReader)
{
auto ptr = ToPtrManifest (hReader);
if (!ptr) return nullptr;
switch (ptr->type ())
{
case PackageType::single: {
auto reader = ptr->appx_reader ();
auto app = reader.applications ();
auto appvec = new app_enumerator ();
app.applications (*appvec);
return ToHandleAppEnumerator (appvec);
} break;
}
return nullptr;
}
void DestroyManifestApplications (_In_ HAPPENUMERATOR hEnumerator)
{
auto ptr = ToPtrAppxApps (hEnumerator);
if (ptr) delete ptr;
}
// Resources
HLIST_PVOID GetManifestResourcesLanguages (_In_ HPKGMANIFESTREAD hReader)
{
auto ptr = ToPtrManifest (hReader);
if (!ptr) return nullptr;
std::vector <std::wnstring> langs;
switch (ptr->type ())
{
case PackageType::single:
{
auto reader = ptr->appx_reader ();
auto res = reader.resources ();
res.languages (langs);
break;
}
case PackageType::bundle:
{
auto br = ptr->bundle_reader ();
auto res = br.package_id_items ();
res.enumerate ([&langs] (IAppxBundleManifestPackageInfo *inf) {
auto item = appx_info::appx_iditem (inf);
std::vector <std::wnstring> l;
auto qr = item.qualified_resources ();
qr.languages (l);
for (auto &it : l) push_unique <std::wnstring> (langs, it);
});
break;
}
default: return nullptr;
}
if (langs.empty ()) return nullptr;
size_t count = langs.size ();
size_t bytes = sizeof (LIST_PVOID) + sizeof (LPWSTR) * (count - 1);
auto list = (HLIST_PVOID)malloc (bytes);
ZeroMemory (list, bytes);
if (!list) return nullptr;
list->dwSize = 0;
for (auto &it : langs) list->alpVoid [list->dwSize ++] = _wcsdup (it.c_str ());
return list;
}
HLIST_LCID GetManifestResourcesLanguagesToLcid (_In_ HPKGMANIFESTREAD hReader)
{
auto ptr = ToPtrManifest (hReader);
if (!ptr) return nullptr;
std::vector <std::wnstring> langs;
switch (ptr->type ())
{
case PackageType::single:
{
auto reader = ptr->appx_reader ();
auto res = reader.resources ();
res.languages (langs);
break;
}
case PackageType::bundle:
{
auto br = ptr->bundle_reader ();
auto res = br.package_id_items ();
res.enumerate ([&langs] (IAppxBundleManifestPackageInfo *inf) {
auto item = appx_info::appx_iditem (inf);
std::vector <std::wnstring> l;
auto qr = item.qualified_resources ();
qr.languages (l);
for (auto &it : l) push_unique <std::wnstring> (langs, it);
});
break;
}
default: return nullptr;
}
if (langs.empty ()) return nullptr;
size_t len = sizeof (LIST_LCID) + sizeof (LCID) * langs.size ();
HLIST_LCID hList = (HLIST_LCID)malloc (len);
ZeroMemory (hList, len);
hList->dwSize = 0;
for (auto &it : langs)
{
LCID lcid = LocaleCodeToLcid (it);
if (lcid)
{
hList->aLcid [hList->dwSize ++] = lcid;
}
}
return hList;
}
HLIST_UINT32 GetManifestResourcesScales (_In_ HPKGMANIFESTREAD hReader)
{
auto ptr = ToPtrManifest (hReader);
if (!ptr) return nullptr;
std::vector <UINT32> scales;
switch (ptr->type ())
{
case PackageType::single:
{
auto reader = ptr->appx_reader ();
auto res = reader.resources ();
res.scales (scales);
break;
}
case PackageType::bundle:
{
auto br = ptr->bundle_reader ();
auto res = br.package_id_items ();
res.enumerate ([&scales] (IAppxBundleManifestPackageInfo *inf) {
auto item = appx_info::appx_iditem (inf);
std::vector <UINT32> s;
auto qr = item.qualified_resources ();
qr.scales (s);
for (auto &it : s) push_unique (scales, it);
});
break;
}
default: return nullptr;
}
if (scales.empty ()) return nullptr;
size_t len = sizeof (LIST_UINT32) + sizeof (UINT32) * scales.size ();
HLIST_UINT32 hList = (HLIST_UINT32)malloc (len);
ZeroMemory (hList, len);
hList->dwSize = 0;
for (auto &it : scales)
{
if (!it) continue;
hList->aUI32 [hList->dwSize ++] = it;
}
return hList;
}
DWORD GetManifestResourcesDxFeatureLevels (_In_ HPKGMANIFESTREAD hReader)
{
auto ptr = ToPtrManifest (hReader);
if (!ptr) return 0;
DWORD dwFlags = 0;
switch (ptr->type ())
{
case PackageType::single:
{
auto reader = ptr->appx_reader ();
auto res = reader.resources ();
std::vector <DX_FEATURE_LEVEL> dxlevels;
res.dx_feature_level (dxlevels);
for (auto &it : dxlevels)
{
switch (it)
{
case DX_FEATURE_LEVEL::DX_FEATURE_LEVEL_9:
dwFlags |= PKG_RESOURCES_DXFEATURE_LEVEL9; break;
case DX_FEATURE_LEVEL::DX_FEATURE_LEVEL_10:
dwFlags |= PKG_RESOURCES_DXFEATURE_LEVEL10; break;
case DX_FEATURE_LEVEL::DX_FEATURE_LEVEL_11:
dwFlags |= PKG_RESOURCES_DXFEATURE_LEVEL11; break;
case (DX_FEATURE_LEVEL)4:
dwFlags |= PKG_RESOURCES_DXFEATURE_LEVEL12; break;
}
}
break;
}
case PackageType::bundle:
{
auto br = ptr->bundle_reader ();
auto res = br.package_id_items ();
res.enumerate ([&dwFlags] (IAppxBundleManifestPackageInfo *inf) {
auto item = appx_info::appx_iditem (inf);
std::vector <DX_FEATURE_LEVEL> dxlevels;
auto qr = item.qualified_resources ();
qr.dx_feature_level (dxlevels);
for (auto &it : dxlevels)
{
switch (it)
{
case DX_FEATURE_LEVEL::DX_FEATURE_LEVEL_9:
dwFlags |= PKG_RESOURCES_DXFEATURE_LEVEL9; break;
case DX_FEATURE_LEVEL::DX_FEATURE_LEVEL_10:
dwFlags |= PKG_RESOURCES_DXFEATURE_LEVEL10; break;
case DX_FEATURE_LEVEL::DX_FEATURE_LEVEL_11:
dwFlags |= PKG_RESOURCES_DXFEATURE_LEVEL11; break;
case (DX_FEATURE_LEVEL)4:
dwFlags |= PKG_RESOURCES_DXFEATURE_LEVEL12; break;
}
}
});
break;
}
default: return 0;
}
return dwFlags;
}
// Dependencies
HLIST_DEPINFO GetManifestDependencesInfoList (_In_ HPKGMANIFESTREAD hReader)
{
auto ptr = ToPtrManifest (hReader);
if (!ptr) return nullptr;
std::vector <dep_info> vec;
switch (ptr->type ())
{
case PackageType::single: {
auto reader = ptr->appx_reader ();
auto deps = reader.dependencies ();
deps.dependencies (vec);
} break;
}
size_t len = sizeof (LIST_DEPINFO) + sizeof (DEPENDENCY_INFO) * vec.size ();
HLIST_DEPINFO hList = (HLIST_DEPINFO)malloc (len);
ZeroMemory (hList, len);
hList->dwSize = 0;
for (auto &it : vec)
{
auto &dep = hList->aDepInfo [hList->dwSize ++];
dep.lpName = _wcsdup (it.name.c_str ());
dep.lpPublisher = _wcsdup (it.publisher.c_str ());
dep.verMin = VersionClassToStruct (it.minversion);
}
return hList;
}
// Capabilities
HLIST_PVOID GetManifestCapabilitiesList (_In_ HPKGMANIFESTREAD hReader)
{
auto ptr = ToPtrManifest (hReader);
if (!ptr) return nullptr;
std::vector <std::wnstring> caps;
switch (ptr->type ())
{
case PackageType::single: {
auto reader = ptr->appx_reader ();
auto cap = reader.capabilities ();
std::vector <std::wstring> vec;
cap.capabilities_names (vec);
for (auto &it : vec)
{
auto cname = std::wnstring (it.c_str ());
if (cname.empty ()) continue;
push_unique (caps, cname);
}
} break;
}
size_t len = sizeof (LIST_PVOID) + sizeof (LPWSTR) * caps.size ();
HLIST_PVOID hList = (HLIST_PVOID)malloc (len);
ZeroMemory (hList, len);
hList->dwSize = 0;
for (auto &it : caps)
{
hList->alpVoid [hList->dwSize ++] = (LPVOID)_wcsdup (it.c_str ());
}
return hList;
}
HLIST_PVOID GetManifestDeviceCapabilitiesList (_In_ HPKGMANIFESTREAD hReader)
{
auto ptr = ToPtrManifest (hReader);
if (!ptr) return nullptr;
std::vector <std::wnstring> caps;
switch (ptr->type ())
{
case PackageType::single: {
auto reader = ptr->appx_reader ();
auto cap = reader.capabilities ();
std::vector <std::wstring> vec;
cap.device_capabilities (vec);
for (auto &it : vec)
{
auto cname = std::wnstring (it.c_str ());
if (cname.empty ()) continue;
push_unique (caps, cname);
}
} break;
}
size_t len = sizeof (LIST_PVOID) + sizeof (LPWSTR) * caps.size ();
HLIST_PVOID hList = (HLIST_PVOID)malloc (len);
ZeroMemory (hList, len);
hList->dwSize = 0;
for (auto &it : caps)
{
hList->alpVoid [hList->dwSize ++] = (LPVOID)_wcsdup (it.c_str ());
}
return hList;
}
// Prerequisite
BOOL GetManifestPrerequisite (_In_ HPKGMANIFESTREAD hReader, _In_ LPCWSTR lpName, _Outptr_ VERSION *pVerRet)
{
auto ptr = ToPtrManifest (hReader);
if (!ptr) return FALSE;
switch (ptr->type ())
{
case PackageType::single: {
auto reader = ptr->appx_reader ();
auto pre = reader.prerequisites ();
auto ver = pre.get_version (lpName ? lpName : L"");
*pVerRet = VersionClassToStruct (ver);
return !ver.empty ();
} break;
}
return FALSE;
}

View File

@@ -87,7 +87,7 @@ extern "C"
#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);
@@ -286,6 +286,155 @@ extern "C"
// 获取功能名的显示名,如 internetClient 对应“访问您的 Internet 连接”。返回的是适应于系统区域语言的文本。
// 注意:返回的字符串一定要通过 free 释放。
PKGREAD_API LPWSTR GetPackageCapabilityDisplayName (LPCWSTR lpCapabilityName);
// 释放从本库中返回的字符串
// 其实通过 free 释放即可,但考虑到环境问题,那么另写了个函数
PKGREAD_API void PackageReaderFreeString (LPWSTR lpStrFromThisDll);
// ========= 以下是针对于应用清单的读取器,一些常量和类型等是复用的 =========
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);
#ifdef _DEFAULT_INIT_VALUE_
#undef _DEFAULT_INIT_VALUE_
#endif

View File

@@ -1336,3 +1336,202 @@ class package
appxreader appx_reader () const { return appxreader (*(IAppxPackageReader **)&this->appx); }
bundlereader bundle_reader () const { return bundlereader (*(IAppxBundleReader **)&this->bundle); }
};
class appxmanifest: virtual public com_info_quote <IAppxManifestReader>
{
using Base = com_info_quote <IAppxManifestReader>;
template <typename IComPtr, typename ReturnType, typename Fn> HRESULT get (IComPtr iptr, Fn func, ReturnType *retvalue) const { if (!iptr) return E_FAIL; return (iptr->*func) (retvalue); }
using Manifest = IAppxManifestReader;
public:
using Base::Base;
Manifest *manifest () { return pointer (); }
template <class IComPtr, class Func> HRESULT get_from_manifest (Func fn, _Outptr_ IComPtr *output) const
{
if (!pointer ()) return E_FAIL;
return get (pointer (), fn, output);
}
HRESULT get_identity (_Outptr_ IAppxManifestPackageId **output) const { return get_from_manifest <IAppxManifestPackageId *> (&Manifest::GetPackageId, output); }
appx_info::appx_id identity () const
{
IAppxManifestPackageId *ip = nullptr;
get_identity (&ip);
return appx_info::appx_id (ip);
}
appx_info::appx_res resources () const
{
return appx_info::appx_res (pointer ());
}
HRESULT get_properties (_Outptr_ IAppxManifestProperties **output) const { return get_from_manifest <IAppxManifestProperties *> (&Manifest::GetProperties, output); }
appx_info::appx_prop properties () const
{
IAppxManifestProperties *ip = nullptr;
HRESULT hr = get_properties (&ip);
return appx_info::appx_prop (ip);
}
appx_info::appx_preq prerequisites () const
{
return appx_info::appx_preq (pointer ());
}
HRESULT get_applications (_Outptr_ IAppxManifestApplicationsEnumerator **output) const { return get_from_manifest <IAppxManifestApplicationsEnumerator *> (&Manifest::GetApplications, output); }
appx_info::appx_apps applications () const
{
IAppxManifestApplicationsEnumerator *ip = nullptr;
get_applications (&ip);
return appx_info::appx_apps (ip);
}
HRESULT get_capabilities (_Outptr_ APPX_CAPABILITIES *output) const { return get_from_manifest <APPX_CAPABILITIES> (&Manifest::GetCapabilities, output); }
HRESULT get_device_capabilities (_Outptr_ IAppxManifestDeviceCapabilitiesEnumerator **output) const { return get_from_manifest <IAppxManifestDeviceCapabilitiesEnumerator *> (&Manifest::GetDeviceCapabilities, output); }
appx_info::appx_capabs capabilities () const
{
APPX_CAPABILITIES caps;
IAppxManifestDeviceCapabilitiesEnumerator *ip = nullptr;
if (pointer ()) pointer ()->GetDeviceCapabilities (&ip);
auto im = pointer ();
if (SUCCEEDED (get_capabilities (&caps))) return appx_info::appx_capabs (ip, caps, im);
return appx_info::appx_capabs (ip);
}
HRESULT get_dependencies (_Outptr_ IAppxManifestPackageDependenciesEnumerator **output) const { return get_from_manifest <IAppxManifestPackageDependenciesEnumerator *> (&Manifest::GetPackageDependencies, output); }
appx_info::appx_deps dependencies () const
{
IAppxManifestPackageDependenciesEnumerator *ip = nullptr;
get_dependencies (&ip);
return appx_info::appx_deps (ip);
}
PackageRole package_role () const
{
auto prop = properties ();
if (prop.framework ()) return PackageRole::framework;
try { if (prop.resource_package ()) return PackageRole::resource; }
catch (const std::exception &e) {}
auto app = applications ();
std::vector <std::wstring> apps;
if (app.app_user_model_ids (apps)) return PackageRole::application;
else return PackageRole::unknown;
}
};
class bundlemanifest: virtual public com_info_quote <IAppxBundleManifestReader>
{
using Base = com_info_quote <IAppxBundleManifestReader>;
public:
using Base::Base;
template <typename IComPtr, typename ReturnType, typename Fn> HRESULT get (IComPtr iptr, Fn func, ReturnType *retvalue) const { if (!iptr) return E_FAIL; return (iptr->*func) (retvalue); }
using Manifest = IAppxBundleManifestReader;
Manifest *manifest () { return pointer (); }
template <class IComPtr, class Func> HRESULT get_from_manifest (Func fn, _Outptr_ IComPtr *output) const
{
if (!pointer ()) return E_FAIL;
return get (pointer (), fn, output);
}
HRESULT get_identity (_Outptr_ IAppxManifestPackageId **output) const { return get_from_manifest (&Manifest::GetPackageId, output); }
appx_info::appx_id identity () const
{
IAppxManifestPackageId *ip = nullptr;
get_identity (&ip);
return appx_info::appx_id (ip);
}
HRESULT get_package_id_items (_Outptr_ IAppxBundleManifestPackageInfoEnumerator **output) const { return get_from_manifest (&Manifest::GetPackageInfoItems, output); }
appx_info::appx_iditems package_id_items () const
{
IAppxBundleManifestPackageInfoEnumerator *ip = nullptr;
get_package_id_items (&ip);
return appx_info::appx_iditems (ip);
}
};
HRESULT GetAppxManifestReader (_In_ LPCWSTR inputPath, _Outptr_ IAppxManifestReader **manifestReader)
{
if (!manifestReader) return E_POINTER;
*manifestReader = nullptr;
HRESULT hr;
CComPtr <IStream> stream;
CComPtr <IAppxFactory> factory;
CComPtr <IAppxPackageReader> packageReader;
hr = SHCreateStreamOnFileEx (
inputPath,
STGM_READ | STGM_SHARE_DENY_NONE,
FILE_ATTRIBUTE_NORMAL,
FALSE,
nullptr,
&stream
);
if (FAILED (hr)) return hr;
hr = CoCreateInstance (
__uuidof (AppxFactory),
nullptr,
CLSCTX_INPROC_SERVER,
IID_PPV_ARGS (&factory)
);
if (FAILED (hr)) return hr;
hr = factory->CreatePackageReader (stream, &packageReader);
if (SUCCEEDED (hr))
{
return packageReader->GetManifest (manifestReader);
}
hr = factory->CreateManifestReader (stream, manifestReader);
return hr;
}
HRESULT GetBundleManifestReader (_In_ LPCWSTR bundlePath, _Outptr_ IAppxBundleManifestReader **manifestReader)
{
if (!manifestReader) return E_POINTER;
*manifestReader = nullptr;
HRESULT hr;
CComPtr <IStream> stream;
CComPtr <IAppxBundleFactory> factory;
CComPtr <IAppxBundleReader> bundleReader;
hr = SHCreateStreamOnFileEx (
bundlePath,
STGM_READ | STGM_SHARE_DENY_NONE,
FILE_ATTRIBUTE_NORMAL,
FALSE,
nullptr,
&stream
);
if (FAILED (hr)) return hr;
hr = CoCreateInstance (
__uuidof(AppxBundleFactory),
nullptr,
CLSCTX_INPROC_SERVER,
IID_PPV_ARGS (&factory)
);
if (FAILED (hr)) return hr;
hr = factory->CreateBundleReader (stream, &bundleReader);
if (FAILED (hr)) return hr;
hr = bundleReader->GetManifest (manifestReader);
if (FAILED (hr)) return hr = factory->CreateBundleManifestReader (stream, manifestReader);
return hr;
}
class manifest
{
IAppxManifestReader *appx = nullptr;
IAppxBundleManifestReader *bundle = nullptr;
public:
~manifest () { destroy (); }
manifest (const std::wstring &filepath = L"") { create (filepath); }
void destroy ()
{
if (appx) { appx->Release (); appx = nullptr; }
if (bundle) { bundle->Release (); bundle = nullptr; }
}
bool create (const std::wstring &filepath)
{
destroy ();
if (!IsFileExists (filepath)) return false;
HRESULT hr = GetBundleManifestReader (filepath.c_str (), &bundle);
if (SUCCEEDED (hr)) return true;
if (bundle) { bundle->Release (); bundle = nullptr; }
hr = GetAppxManifestReader (filepath.c_str (), &appx);
if (SUCCEEDED (hr)) return true;
if (appx) { appx->Release (); appx = nullptr; }
return false;
}
bool valid () const { return (bool)appx ^ (bool)bundle; }
PackageType type () const
{
if (appx) return PackageType::single;
if (bundle) return PackageType::bundle;
return PackageType::unknown;
}
appxmanifest appx_reader () const { return appxmanifest (*(IAppxManifestReader **)&this->appx); }
bundlemanifest bundle_reader () const { return bundlemanifest (*(IAppxBundleManifestReader **)&this->bundle); }
};