Files
App-Installer-For-Windows-8…/appinstaller/appxinfo.h
2025-11-28 16:47:12 +08:00

351 lines
12 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#pragma once
#include <Windows.h>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <rapidjson\document.h>
#include <rapidjson\writer.h>
#include <rapidjson\stringbuffer.h>
#include <codecvt>
#include <locale>
#include "nstring.h"
#include "priformatcli.h"
#include "pkgread.h"
static std::string ws2utf8 (const std::wstring &ws)
{
std::wstring_convert <std::codecvt_utf8 <wchar_t>> conv;
return conv.to_bytes (ws);
}
static rapidjson::Value ver_to_json (const VERSION &ver, rapidjson::Document::AllocatorType &alloc)
{
rapidjson::Value obj (rapidjson::kObjectType);
obj.AddMember ("major", ver.major, alloc);
obj.AddMember ("minor", ver.minor, alloc);
obj.AddMember ("build", ver.build, alloc);
obj.AddMember ("revision", ver.revision, alloc);
return obj;
}
struct pkginfo
{
std::wstring filepath;
bool valid = false;
// 包的类型Appx 包还是 AppxBundle 包。返回 PKGTYPE_* 宏
WORD type = 0;
// 包的类型:是应用包、框架包还是资源包。
// 对于 AppxBundle 包永远返回是资源包(因为框架包无法打包成 AppxBundle资源包必须与应用包一同打包进 AppxBundle
// 返回 PKGROLE_* 宏。
WORD role = 0;
struct
{
std::wstring name,
publisher,
package_family_name,
package_full_name,
resource_id;
VERSION version, realver;
DWORD architecture;
} identity;
// x86: 0
// x64: 9
// Arm: 5
// Neutral: 11
// Arm64: 12
std::set <WORD> get_architectures () const
{
std::set <WORD> ret;
switch (type)
{
case PKGTYPE_APPX: {
switch (identity.architecture)
{
case PKG_ARCHITECTURE_X86: ret.insert (0); break;
case PKG_ARCHITECTURE_X64: ret.insert (9); break;
case PKG_ARCHITECTURE_ARM: ret.insert (5); break;
case PKG_ARCHITECTURE_ARM64: ret.insert (12); break;
case PKG_ARCHITECTURE_NEUTRAL: ret.insert (11); break;
}
} break;
case PKGTYPE_BUNDLE: {
if (identity.architecture & PKG_ARCHITECTURE_X86) ret.insert (0);
if (identity.architecture & PKG_ARCHITECTURE_X64) ret.insert (9);
if (identity.architecture & PKG_ARCHITECTURE_ARM) ret.insert (5);
if (identity.architecture & PKG_ARCHITECTURE_ARM64) ret.insert (12);
// 由于架构历史发展原因:这样做是对的。
if (identity.architecture & (PKG_ARCHITECTURE_X86 | PKG_ARCHITECTURE_X64 | PKG_ARCHITECTURE_ARM))
{ ret.clear (); ret.insert (11); }
if (identity.architecture & PKG_ARCHITECTURE_NEUTRAL) { ret.clear (); ret.insert (11); }
}
}
return ret;
}
struct
{
std::wstring display_name;
std::wstring publisher_display_name;
std::wstring description;
std::wstring logo;
std::wstring logo_base64;
bool framework = false;
bool resource_package = false;
} properties;
struct application: std::map <std::wnstring, std::wstring>
{
using base = std::map <std::wnstring, std::wstring>;
using base::base;
application () = default;
std::wstring user_model_id () { return this->at (L"AppUserModelID"); }
friend bool operator == (application &a1, application &a2) { return a1.user_model_id () == a2.user_model_id (); }
friend bool operator != (application &a1, application &a2) { return a1.user_model_id () != a2.user_model_id (); }
explicit operator bool () { return this->user_model_id ().empty (); }
};
std::vector <application> applications;
struct
{
std::vector <std::wnstring> capabilities_name;
std::vector <std::wnstring> device_capabilities;
} capabilities;
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) {}
};
std::vector <dependency> dependencies;
struct
{
std::set <std::wnstring> languages;
std::set <UINT32> scales;
// PKG_RESOURCES_DXFEATURE_LEVEL* 前缀常量
std::set <DWORD> dx_feature_levels;
} resources;
struct
{
VERSION os_min_version, os_max_version_tested;
std::wstring os_min_version_description, os_max_version_tested_description;
} prerequisites;
static pkginfo parse (const std::wstring &filepath)
{
pkginfo pkg;
pkg.filepath = filepath;
package_reader pread (filepath);
pread.use_pri (true);
pread.enable_pri_convert (true);
pkg.valid = pread.valid ();
if (!pkg.valid) return pkg;
pkg.type = pread.package_type ();
pkg.role = pread.package_role ();
{
auto id = pread.get_identity ();
pkg.identity.architecture = id.architecture ();
pkg.identity.name = id.name ();
pkg.identity.package_family_name = id.package_family_name ();
pkg.identity.package_full_name = id.package_full_name ();
pkg.identity.publisher = id.publisher ();
pkg.identity.resource_id = id.resource_id ();
pkg.identity.version = id.version ();
pkg.identity.realver = id.version (true);
}
{
auto prop = pread.get_properties ();
pkg.properties.description = prop.description ();
pkg.properties.display_name = prop.display_name ();
pkg.properties.framework = prop.framework ();
pkg.properties.logo = prop.logo ();
pkg.properties.logo_base64 = prop.logo_base64 ();
pkg.properties.publisher_display_name = prop.publisher_display_name ();
pkg.properties.resource_package = prop.resource_package ();
}
{
auto prer = pread.get_prerequisites ();
pkg.prerequisites.os_min_version = prer.os_min_version ();
pkg.prerequisites.os_max_version_tested = prer.os_max_version_tested ();
pkg.prerequisites.os_min_version_description = prer.os_min_version_description ();
pkg.prerequisites.os_max_version_tested_description = prer.os_max_version_tested_description ();
}
{
auto apps = pread.get_applications ();
std::vector <package_reader::application> appmap;
apps.get (appmap);
pkg.applications.reserve (appmap.size ());
for (auto &mp : appmap)
{
application app;
for (auto &it : mp)
{
if (std::find (g_filepathitems.begin (), g_filepathitems.end (), it.first) != g_filepathitems.end ())
app [it.first] = mp.newat_base64 (it.first);
else app [it.first] = mp.newat (it.first);
}
pkg.applications.push_back (app);
}
}
{
auto caps = pread.get_capabilities ();
std::vector <std::wstring> vws;
caps.capabilities_name (vws);
pkg.capabilities.capabilities_name.reserve (vws.size ());
for (auto &it : vws) pkg.capabilities.capabilities_name.push_back (it);
vws.clear ();
caps.device_capabilities (vws);
pkg.capabilities.device_capabilities.reserve (vws.size ());
for (auto &it : vws) pkg.capabilities.device_capabilities.push_back (it);
}
{
std::vector <package_reader::dependency> deps;
auto depr = pread.get_dependencies ();
pkg.dependencies.reserve (depr.get (deps));
for (auto &it : deps)
{
dependency dep;
dep.name = it.name;
dep.publisher = it.publisher;
dep.vermin = it.vermin;
pkg.dependencies.push_back (dep);
}
}
{
auto ress = pread.get_resources ();
{
std::vector <std::wstring> langs;
ress.languages (langs);
for (auto &it : langs) pkg.resources.languages.insert (it);
}
{
std::vector <UINT32> ss;
ress.scales (ss);
for (auto &it : ss) pkg.resources.scales.insert (it);
}
{
DWORD dx = ress.dx_feature_level ();
if (dx & PKG_RESOURCES_DXFEATURE_LEVEL9)
pkg.resources.dx_feature_levels.insert (PKG_RESOURCES_DXFEATURE_LEVEL9);
else if (dx & PKG_RESOURCES_DXFEATURE_LEVEL10)
pkg.resources.dx_feature_levels.insert (PKG_RESOURCES_DXFEATURE_LEVEL10);
else if (dx & PKG_RESOURCES_DXFEATURE_LEVEL11)
pkg.resources.dx_feature_levels.insert (PKG_RESOURCES_DXFEATURE_LEVEL11);
else if (dx & PKG_RESOURCES_DXFEATURE_LEVEL12)
pkg.resources.dx_feature_levels.insert (PKG_RESOURCES_DXFEATURE_LEVEL12);
}
}
return pkg;
}
std::wstring parseJson ()
{
using namespace rapidjson;
Document doc;
doc.SetObject ();
auto &alloc = doc.GetAllocator ();
doc.AddMember ("filepath", Value (ws2utf8 (filepath).c_str (), alloc), alloc);
doc.AddMember ("valid", valid, alloc);
doc.AddMember ("type", type, alloc);
doc.AddMember ("role", role, alloc);
{
Value obj (kObjectType);
obj.AddMember ("name", Value (ws2utf8 (identity.name).c_str (), alloc), alloc);
obj.AddMember ("publisher", Value (ws2utf8 (identity.publisher).c_str (), alloc), alloc);
obj.AddMember ("package_family_name", Value (ws2utf8 (identity.package_family_name).c_str (), alloc), alloc);
obj.AddMember ("package_full_name", Value (ws2utf8 (identity.package_full_name).c_str (), alloc), alloc);
obj.AddMember ("resource_id", Value (ws2utf8 (identity.resource_id).c_str (), alloc), alloc);
obj.AddMember ("architecture", (uint32_t)identity.architecture, alloc);
obj.AddMember ("version", ver_to_json (identity.version, alloc), alloc);
obj.AddMember ("realver", ver_to_json (identity.realver, alloc), alloc);
doc.AddMember ("identity", obj, alloc);
}
{
Value obj (kObjectType);
obj.AddMember ("display_name", Value (ws2utf8 (properties.display_name).c_str (), alloc), alloc);
obj.AddMember ("publisher_display_name", Value (ws2utf8 (properties.publisher_display_name).c_str (), alloc), alloc);
obj.AddMember ("description", Value (ws2utf8 (properties.description).c_str (), alloc), alloc);
obj.AddMember ("logo", Value (ws2utf8 (properties.logo).c_str (), alloc), alloc);
obj.AddMember ("logo_base64", Value (ws2utf8 (properties.logo_base64).c_str (), alloc), alloc);
obj.AddMember ("framework", properties.framework, alloc);
obj.AddMember ("resource_package", properties.resource_package, alloc);
doc.AddMember ("properties", obj, alloc);
}
{
Value arr (kArrayType);
for (auto &app : applications)
{
Value obj (kObjectType);
for (auto &it : app)
{
std::string key = ws2utf8 (it.first);
std::string val = ws2utf8 (it.second);
obj.AddMember (
Value (key.c_str (), alloc),
Value (val.c_str (), alloc),
alloc
);
}
arr.PushBack (obj, alloc);
}
doc.AddMember ("applications", arr, alloc);
}
{
Value obj (kObjectType);
{
Value arr (kArrayType);
for (auto &it : capabilities.capabilities_name)
arr.PushBack (Value (ws2utf8 (it).c_str (), alloc), alloc);
obj.AddMember ("capabilities_name", arr, alloc);
}
{
Value arr (kArrayType);
for (auto &it : capabilities.device_capabilities) arr.PushBack (Value (ws2utf8 (it).c_str (), alloc), alloc);
obj.AddMember ("device_capabilities", arr, alloc);
}
doc.AddMember ("capabilities", obj, alloc);
}
{
Value arr (kArrayType);
for (auto& d : dependencies)
{
Value obj (kObjectType);
obj.AddMember ("name", Value (ws2utf8 (d.name).c_str (), alloc), alloc);
obj.AddMember ("publisher", Value (ws2utf8 (d.publisher).c_str (), alloc), alloc);
obj.AddMember ("vermin", ver_to_json (d.vermin, alloc), alloc);
arr.PushBack (obj, alloc);
}
doc.AddMember ("dependencies", arr, alloc);
}
{
Value obj (kObjectType);
{
Value arr (kArrayType);
for (auto &it : resources.languages) arr.PushBack (Value (ws2utf8 (it).c_str (), alloc), alloc);
obj.AddMember ("languages", arr, alloc);
}
{
Value arr (kArrayType);
for (auto &it : resources.scales) arr.PushBack ((uint32_t)it, alloc);
obj.AddMember ("scales", arr, alloc);
}
{
Value arr (kArrayType);
for (auto &it : resources.dx_feature_levels) arr.PushBack ((uint32_t)it, alloc);
obj.AddMember ("dx_feature_levels", arr, alloc);
}
doc.AddMember ("resources", obj, alloc);
}
{
Value obj (kObjectType);
obj.AddMember ("os_min_version", ver_to_json (prerequisites.os_min_version, alloc), alloc);
obj.AddMember ("os_max_version_tested", ver_to_json (prerequisites.os_max_version_tested, alloc), alloc);
obj.AddMember ("os_min_version_description", Value (ws2utf8 (prerequisites.os_min_version_description).c_str (), alloc), alloc);
obj.AddMember ("os_max_version_tested_description", Value (ws2utf8 (prerequisites.os_max_version_tested_description).c_str (), alloc), alloc);
doc.AddMember ("prerequisites", obj, alloc);
}
StringBuffer buffer;
Writer <StringBuffer> writer (buffer);
doc.Accept (writer);
std::string utf8 = buffer.GetString ();
std::wstring_convert <std::codecvt_utf8 <wchar_t>> conv;
return conv.from_bytes (utf8);
}
};