mirror of
https://github.com/modernw/App-Installer-For-Windows-8.x-Reset.git
synced 2026-04-11 17:57:19 +10:00
351 lines
12 KiB
C++
351 lines
12 KiB
C++
#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);
|
||
}
|
||
};
|