// pkgread.cpp : 定义 DLL 应用程序的导出函数。 // #include "stdafx.h" #include "readobj.h" #include "pkgread.h" #include "localeex.h" #include "themeinfo.h" #define ToHandleRead(_cpp_ptr_) reinterpret_cast (_cpp_ptr_) #define ToPtrPackage(_cpp_ptr_) reinterpret_cast (_cpp_ptr_) HPKGREAD CreatePackageReader () { return ToHandleRead (new package ()); } BOOL LoadPackageFromFile (_In_ HPKGREAD hReader, _In_ LPCWSTR lpFilePath) { auto ptr = ToPtrPackage (hReader); if (!ptr) return false; return ptr->create (lpFilePath); } void DestroyPackageReader (_In_ HPKGREAD hReader) { auto ptr = ToPtrPackage (hReader); if (!ptr) return; return delete ptr; } WORD GetPackageType (_In_ HPKGREAD hReader) { auto ptr = ToPtrPackage (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 IsPackageValid (_In_ HPKGREAD hReader) { auto ptr = ToPtrPackage (hReader); if (!ptr) return false; return ptr->valid (); } WORD GetPackageRole (_In_ HPKGREAD hReader) { auto ptr = ToPtrPackage (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 VERSION VersionClassToStruct (const version &v) { VERSION sv; sv.major = v.major; sv.minor = v.minor; sv.build = v.build; sv.revision = v.revision; return sv; } LPWSTR GetPackageIdentityStringValue (_In_ HPKGREAD hReader, _In_ DWORD dwName) { auto ptr = ToPtrPackage (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 (); if (HIWORD (dwName) == PKGTYPE_BUNDLE) { CComPtr apkg; HRESULT hr = reader.random_application_package (&apkg); if (SUCCEEDED (hr)) { appxreader aread (apkg.p); auto aid = aread.identity (); switch (LOWORD (dwName)) { case PKG_IDENTITY_NAME: return _wcsdup (aid.name ().c_str ()); case PKG_IDENTITY_PUBLISHER: return _wcsdup (aid.publisher ().c_str ()); case PKG_IDENTITY_PACKAGEFAMILYNAME: return _wcsdup (aid.package_family_name ().c_str ()); case PKG_IDENTITY_PACKAGEFULLNAME: return _wcsdup (aid.package_full_name ().c_str ()); case PKG_IDENTITY_RESOURCEID: return _wcsdup (aid.resource_id ().c_str ()); } } } else { 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 GetPackageIdentityVersion (_In_ HPKGREAD hReader, _Out_ VERSION *pVersion, _In_ BOOL bGetSubPkgVer) { auto ptr = ToPtrPackage (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 (); if (bGetSubPkgVer) { CComPtr apkg; HRESULT hr = reader.random_application_package (&apkg); if (SUCCEEDED (hr)) { appxreader aread (apkg.p); auto aid = aread.identity (); auto ver = aid.version (); *pVersion = VersionClassToStruct (ver); return !ver.empty (); } } else { auto ver = id.version (); *pVersion = VersionClassToStruct (ver); return !ver.empty (); } } break; } return FALSE; } BOOL GetPackageIdentityArchitecture (_In_ HPKGREAD hReader, _Out_ DWORD *pdwArchi) { auto ptr = ToPtrPackage (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 (); DWORD ret = 0; size_t size = reader.application_packages ([&ret] (IAppxPackageReader *p) { appxreader aread (p); auto id = aread.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 GetPackagePropertiesStringValue (_In_ HPKGREAD hReader, _In_ LPCWSTR lpName) { auto ptr = ToPtrPackage (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; case PackageType::bundle: { auto reader = ptr->bundle_reader (); CComPtr apppkg; if (SUCCEEDED (reader.random_application_package (&apppkg))) { appxreader apkg (apppkg.p); auto prop = apkg.properties (); return _wcsdup (prop.string_value (lpName ? lpName : L"").c_str ()); } } break; } return nullptr; } HRESULT GetPackagePropertiesBoolValue (_In_ HPKGREAD hReader, _In_ LPCWSTR lpName, _Outptr_ BOOL *pRet) { auto ptr = ToPtrPackage (hReader); if (!ptr) return E_INVALIDARG; if (!pRet) return E_INVALIDARG; *pRet = FALSE; switch (ptr->type ()) { case PackageType::single: { auto reader = ptr->appx_reader (); CComPtr m; HRESULT hr = reader.manifest (&m); if (FAILED (hr)) return hr; CComPtr p; hr = m->GetProperties (&p); if (FAILED (hr)) return hr; return p->GetBoolValue (lpName, pRet); } break; case PackageType::bundle: { auto reader = ptr->bundle_reader (); CComPtr apppkg; HRESULT hr = S_OK; if (SUCCEEDED (hr = reader.random_application_package (&apppkg))) { appxreader apkg (apppkg.p); CComPtr m; hr = apkg.manifest (&m); if (FAILED (hr)) return hr; CComPtr p; hr = m->GetProperties (&p); if (FAILED (hr)) return hr; return p->GetBoolValue (lpName, pRet); } else return hr; } break; } return E_FAIL; } // Applications BOOL AddPackageApplicationItemGetName (_In_ LPCWSTR lpName) { if (std::wnstring (lpName ? lpName : L"").empty ()) return FALSE; return PushApplicationAttributeItem (lpName); } BOOL RemovePackageApplicationItemGetName (_In_ LPCWSTR lpName) { if (std::wnstring (lpName ? lpName : L"").empty ()) return FALSE; return RemoveApplicationAttributeItem (lpName); } HLIST_PVOID GetAllApplicationItemsName () { size_t len = sizeof (LIST_PVOID) + sizeof (LPCWSTR) * appitems.size (); HLIST_PVOID hList = (HLIST_PVOID)malloc (len); ZeroMemory (hList, len); hList->dwSize = 0; try { for (auto &it : appitems) { ((LPCWSTR *)hList->alpVoid) [hList->dwSize ++] = (LPCWSTR)it.c_str (); } } catch (const std::exception &e) {} return hList; } void DestroyApplicationItemsName (_In_ HLIST_PVOID hList) { if (!hList) return; free (hList); } #define ToHandleAppEnumerator(_cpp_ptr_) reinterpret_cast (_cpp_ptr_) typedef std::vector app_enumerator; #define ToPtrAppxApps(_cpp_ptr_) reinterpret_cast (_cpp_ptr_) HAPPENUMERATOR GetPackageApplications (_In_ HPKGREAD hReader) { auto ptr = ToPtrPackage (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; case PackageType::bundle: { auto br = ptr->bundle_reader (); CComPtr pr; HRESULT hr = br.random_application_package (&pr); if (SUCCEEDED (hr)) { appxreader reader (pr.p); auto app = reader.applications (); auto appvec = new app_enumerator (); app.applications (*appvec); return ToHandleAppEnumerator (appvec); } } break; } return nullptr; } HLIST_PVOID ApplicationsToMap (_In_ HAPPENUMERATOR hEnumerator) { auto ptr = ToPtrAppxApps (hEnumerator); if (!ptr || ptr->empty ()) return nullptr; size_t count = ptr->size (); size_t len = sizeof (LIST_PVOID) + sizeof (LPVOID) * count; auto list = (HLIST_PVOID)malloc (len); ZeroMemory (list, len); if (!list) return nullptr; list->dwSize = 0; bool outer_throw = false; raii list_guard ([&] () { if (outer_throw) { for (DWORD i = 0; i < list->dwSize; ++i) { auto map = (HLIST_PVOID)list->alpVoid [i]; if (map) { for (DWORD j = 0; j < map->dwSize; ++j) { auto pair = (HPAIR_PVOID)map->alpVoid [j]; if (pair) { free (pair); map->alpVoid [j] = nullptr; } } free (map); list->alpVoid [i] = nullptr; } } free (list); list = nullptr; } }); try { for (auto &app : *ptr) { size_t map_size = app.size (); size_t mlen = sizeof (LIST_PVOID) + sizeof (LPVOID) * map_size; auto map = (HLIST_PVOID)malloc (mlen); ZeroMemory (map, mlen); if (!map) { outer_throw = true; throw std::bad_alloc (); } map->dwSize = 0; bool inner_throw = false; raii map_guard ([&] () { if (inner_throw) { for (DWORD j = 0; j < map->dwSize; ++j) { auto pair = (HPAIR_PVOID)map->alpVoid [j]; if (pair) { free (pair); map->alpVoid [j] = nullptr; } } free (map); map = nullptr; } }); try { for (auto &kv : app) { auto pair = (HPAIR_PVOID)malloc (sizeof (PAIR_PVOID)); ZeroMemory (pair, sizeof (PAIR_PVOID)); if (!pair) { inner_throw = true; throw std::bad_alloc (); } pair->lpKey = (LPVOID)kv.first.c_str (); pair->lpValue = (LPVOID)kv.second.c_str (); map->alpVoid [map->dwSize++] = pair; } } catch (const std::exception &) { inner_throw = true; throw; } list->alpVoid [list->dwSize ++] = map; } } catch (const std::exception &) { outer_throw = true; } if (outer_throw) return nullptr; return list; } void DestroyApplicationsMap (_In_ HLIST_PVOID hEnumerator) { if (!hEnumerator) return; HLIST_PVOID list = hEnumerator; for (DWORD i = 0; i < list->dwSize; ++ i) { HLIST_PVOID map = (HLIST_PVOID)list->alpVoid [i]; if (!map) continue; for (DWORD j = 0; j < map->dwSize; ++ j) { HPAIR_PVOID pair = (HPAIR_PVOID)map->alpVoid [j]; if (pair) { free (pair); map->alpVoid [j] = nullptr; } } free (map); list->alpVoid [i] = nullptr; } free (list); } void DestroyPackageApplications (_In_ HAPPENUMERATOR hEnumerator) { auto ptr = ToPtrAppxApps (hEnumerator); if (ptr) delete ptr; } // Resources HLIST_PVOID GetResourcesLanguages (_In_ HPKGREAD hReader) { auto ptr = ToPtrPackage (hReader); if (!ptr) return nullptr; std::vector 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 l; auto qr = item.qualified_resources (); qr.languages (l); for (auto &it : l) push_unique (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 GetResourcesLanguagesToLcid (_In_ HPKGREAD hReader) { auto ptr = ToPtrPackage (hReader); if (!ptr) return nullptr; std::vector 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 l; auto qr = item.qualified_resources (); qr.languages (l); for (auto &it : l) push_unique (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 GetResourcesScales (_In_ HPKGREAD hReader) { auto ptr = ToPtrPackage (hReader); if (!ptr) return nullptr; std::vector 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 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 GetResourcesDxFeatureLevels (_In_ HPKGREAD hReader) { auto ptr = ToPtrPackage (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 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 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; } void DestroyResourcesLanguagesList (_In_ HLIST_PVOID hList) { if (!hList) return; for (DWORD i = 0; i < hList->dwSize; i++) { if (hList->alpVoid [i]) { free (hList->alpVoid [i]); hList->alpVoid [i] = nullptr; } } free (hList); } void DestroyResourcesLanguagesLcidList (_In_ HLIST_LCID hList) { if (!hList) return; free (hList); } void DestroyUInt32List (_In_ HLIST_UINT32 hList) { if (!hList) return; free (hList); } // Dependencies HLIST_DEPINFO GetDependencesInfoList (_In_ HPKGREAD hReader) { auto ptr = ToPtrPackage (hReader); if (!ptr) return nullptr; std::vector vec; switch (ptr->type ()) { case PackageType::single: { auto reader = ptr->appx_reader (); auto deps = reader.dependencies (); deps.dependencies (vec); } break; case PackageType::bundle: { auto br = ptr->bundle_reader (); CComPtr pr; HRESULT hr = br.random_application_package (&pr); if (FAILED (hr)) return nullptr; appxreader reader (pr.p); auto deps = reader.dependencies (); deps.dependencies (vec); } } 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; } void DestroyDependencesInfoList (_In_ HLIST_DEPINFO hList) { if (!hList) return; for (DWORD i = 0; i < hList->dwSize; i ++) { auto &dep = hList->aDepInfo [i]; if (dep.lpName) { free (dep.lpName); dep.lpName = nullptr; } if (dep.lpPublisher) { free (dep.lpPublisher); dep.lpPublisher = nullptr; } } free (hList); } // Capabilities HLIST_PVOID GetCapabilitiesList (_In_ HPKGREAD hReader) { auto ptr = ToPtrPackage (hReader); if (!ptr) return nullptr; std::vector caps; switch (ptr->type ()) { case PackageType::single: { auto reader = ptr->appx_reader (); auto cap = reader.capabilities (); std::vector 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; case PackageType::bundle: { auto br = ptr->bundle_reader (); CComPtr ar; if (FAILED (br.random_application_package (&ar))) return nullptr; appxreader reader (ar.p); auto cap = reader.capabilities (); std::vector 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 GetDeviceCapabilitiesList (_In_ HPKGREAD hReader) { auto ptr = ToPtrPackage (hReader); if (!ptr) return nullptr; std::vector caps; switch (ptr->type ()) { case PackageType::single: { auto reader = ptr->appx_reader (); auto cap = reader.capabilities (); std::vector 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; case PackageType::bundle: { auto br = ptr->bundle_reader (); CComPtr ar; if (FAILED (br.random_application_package (&ar))) return nullptr; appxreader reader (ar.p); auto cap = reader.capabilities (); std::vector 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; } void DestroyWStringList (_In_ HLIST_PVOID hList) { if (!hList) return; for (size_t cnt = 0; cnt < hList->dwSize; cnt ++) { free (hList->alpVoid [cnt]); hList->alpVoid [cnt] = nullptr; } free (hList); } // Prerequisite BOOL GetPackagePrerequisite (_In_ HPKGREAD hReader, _In_ LPCWSTR lpName, _Outptr_ VERSION *pVerRet) { auto ptr = ToPtrPackage (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; case PackageType::bundle: { auto br = ptr->bundle_reader (); CComPtr ar; HRESULT hr = br.random_application_package (&ar); if (FAILED (hr)) return false; auto reader = appxreader (ar.p); auto pre = reader.prerequisites (); auto ver = pre.get_version (lpName ? lpName : L""); *pVerRet = VersionClassToStruct (ver); return !ver.empty (); } break; } return FALSE; } // Selector std::wnstring SelectLanguageSuitPackageNameByLocaleCode (std::map &in, const std::wstring &langcode, std::wnstring &output) { output.clear (); for (auto &it : in) { if (it.second.restype != appx_info::ResourceType::language) continue; for (auto &it_s : it.second.resvalue.languages) if (LocaleNameCompare (it_s, langcode)) return output = it.first; } return output = L""; } std::wnstring SelectLanguageSuitPackageName (std::map &in, std::wnstring &output) { output.clear (); output = SelectLanguageSuitPackageNameByLocaleCode (in, GetComputerLocaleCodeW (), output); if (output.empty ()) output = SelectLanguageSuitPackageNameByLocaleCode (in, L"en-US", output); if (output.empty ()) { for (auto &it : in) { if (it.second.pkgtype == APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE_APPLICATION) { output = it.first; break; } } } if (output.empty ()) { try { output = in.begin ()->first; } catch (const std::exception &e) { output = L""; } } return output; } std::wnstring SelectScaleSuitPackageName (std::map &in, std::wnstring &output) { output.clear (); struct res_key_value { std::wnstring filename = L""; uint32_t scale = 0; res_key_value (const std::wstring &fpath = L"", uint32_t s = 0): filename (fpath), scale (s) {} }; std::vector rkv; for (auto &it : in) if ((WORD)it.second.restype & (WORD)appx_info::ResourceType::scale) { for (auto &it_s : it.second.resvalue.scales) { if (!it_s) continue; rkv.push_back (res_key_value (it.first, it_s)); } } std::sort (rkv.begin (), rkv.end (), [] (const res_key_value &a, const res_key_value &b) { return a.scale < b.scale; }); auto dpi = GetDPI (); for (auto &it : rkv) if (it.scale > dpi) return output = it.filename; if (output.empty ()) { for (auto it = rkv.rbegin (); it != rkv.rend (); ++ it) if (it->scale < dpi) return output = it->filename; } if (output.empty ()) { for (auto &it : in) if (it.second.pkgtype == APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE_APPLICATION) return output = it.first; } try { output = in.begin ()->first; } catch (const std::exception &e) { output = L""; } return output; } // File Stream HANDLE GetAppxFileFromAppxPackage (_In_ HPKGREAD hReader, _In_ LPCWSTR lpFileName) { auto ptr = ToPtrPackage (hReader); if (!ptr) return nullptr; if (!lpFileName) return nullptr; switch (ptr->type ()) { case PackageType::single: { auto reader = ptr->appx_reader (); CComPtr afile; if (FAILED (reader.payload_stream (lpFileName, &afile))) return nullptr; IStream *istream = nullptr; if (FAILED (afile->GetStream (&istream))) return nullptr; else return istream; } break; case PackageType::bundle: { auto bread = ptr->bundle_reader (); CComPtr appfile; if (FAILED (bread.random_application_package (&appfile))) return nullptr; appxreader reader (appfile.p); CComPtr afile; if (FAILED (reader.payload_stream (lpFileName, &afile))) return nullptr; IStream *istream = nullptr; if (FAILED (afile->GetStream (&istream))) return nullptr; else return istream; } break; } return nullptr; } HANDLE GetAppxBundlePayloadPackageFile (_In_ HPKGREAD hReader, _In_ LPCWSTR lpFileName) { auto ptr = ToPtrPackage (hReader); if (!ptr) return nullptr; if (!lpFileName) return nullptr; if (ptr->type () == PackageType::bundle) { auto reader = ptr->bundle_reader (); CComPtr iafile; if (FAILED (reader.get_payload_package (lpFileName, &iafile))) return nullptr; IStream *istream = nullptr; if (FAILED (iafile->GetStream (&istream))) return nullptr; else return istream; } else return nullptr; } HANDLE GetAppxPriFileStream (_In_ HPKGREAD hReader) { return GetAppxFileFromAppxPackage (hReader, L"resources.pri"); } HANDLE GetFileFromPayloadPackage (_In_ HANDLE hPackageStream, _In_ LPCWSTR lpFileName) { if (!hPackageStream || !lpFileName) return nullptr; IStream *ifs = (IStream *)hPackageStream; CComPtr iappx; if (FAILED (GetAppxPackageReader (ifs, &iappx))) return nullptr; appxreader reader (iappx.p); CComPtr iaf; if (FAILED (reader.payload_stream (lpFileName, &iaf))) return nullptr; IStream *istream = nullptr; if (FAILED (iaf->GetStream (&istream))) return nullptr; else return istream; } HANDLE GetPriFileFromPayloadPackage (_In_ HANDLE hPackageStream) { return GetFileFromPayloadPackage (hPackageStream, L"resources.pri"); } BOOL GetSuitablePackageFromBundle (_In_ HPKGREAD hReader, _Outptr_ HANDLE *pStreamForLang, _Outptr_ HANDLE *pStreamForScale) { auto ptr = ToPtrPackage (hReader); if (!ptr) return FALSE; if (ptr->type () != PackageType::bundle) return FALSE; if (pStreamForLang) *pStreamForLang = nullptr; if (pStreamForScale) *pStreamForScale = nullptr; auto bread = ptr->bundle_reader (); auto pkgsinfo = bread.package_id_items (); std::map mapfr; pkgsinfo.resource_info (mapfr); std::wnstring lf = L"", sf = L""; SelectLanguageSuitPackageName (mapfr, lf); SelectScaleSuitPackageName (mapfr, sf); if (lf == sf) { WORD flag = (bool)pStreamForLang << 1 | (bool)pStreamForScale; switch (flag) { case 0b01: case 0b10: case 0b11: { IStream *file = nullptr; CComPtr pread; if (FAILED (bread.get_payload_package (lf, &pread))) return false; if (FAILED (pread->GetStream (&file))) return false; if (pStreamForLang) *pStreamForLang = file; if (pStreamForScale) *pStreamForScale = file; return true; } break; default: case 0b00: { CComPtr pread; if (FAILED (bread.get_payload_package (lf, &pread))) return false; CComPtr file = nullptr; if (FAILED (pread->GetStream (&file))) return false; else return true; } break; } } else { { CComPtr reslangpkg; if (FAILED (bread.get_payload_package (lf, &reslangpkg))) return false; if (pStreamForLang) { IStream *file = nullptr; if (FAILED (reslangpkg->GetStream (&file))) return false; *pStreamForLang = file; } else { CComPtr file; if (FAILED (reslangpkg->GetStream (&file))) return false; } } { CComPtr resscalepkg; if (FAILED (bread.get_payload_package (sf, &resscalepkg))) return false; if (pStreamForScale) { IStream *file = nullptr; if (FAILED (resscalepkg->GetStream (&file))) return false; *pStreamForScale = file; } else { CComPtr file; if (FAILED (resscalepkg->GetStream (&file))) return false; } } } return true; } ULONG DestroyAppxFileStream (_In_ HANDLE hFileStream) { if (!hFileStream) return 0; IStream *ptr = reinterpret_cast (hFileStream); if (!ptr) return 0; ULONG ret = ptr->Release (); return ret; } HANDLE GetAppxBundleApplicationPackageFile (_In_ HPKGREAD hReader) { if (!hReader) return nullptr; auto ptr = ToPtrPackage (hReader); if (!ptr) return nullptr; switch (ptr->type ()) { case PackageType::single: { return nullptr; } break; case PackageType::bundle: { auto bread = ptr->bundle_reader (); IStream *ipf = nullptr; if (FAILED (bread.random_application_package (&ipf))) return nullptr; else return ipf; } break; } return nullptr; } std::wstring GetMimeTypeFromStream (IStream *filestream) { if (!filestream) return L""; LARGE_INTEGER liZero = {0}; filestream->Seek (liZero, STREAM_SEEK_SET, nullptr); BYTE buffer [256] = {0}; ULONG bytesRead = 0; HRESULT hr = filestream->Read (buffer, sizeof (buffer), &bytesRead); filestream->Seek (liZero, STREAM_SEEK_SET, nullptr); if (FAILED (hr) || bytesRead == 0) return L""; LPWSTR lpMime = nullptr; raii relt ([&lpMime] () { if (lpMime) CoTaskMemFree (lpMime); lpMime = nullptr; }); std::wstring mime; hr = FindMimeFromData ( nullptr, // pBC nullptr, // URL (unknown) buffer, // data buffer bytesRead, // data size nullptr, // proposed MIME FMFD_RETURNUPDATEDIMGMIMES | FMFD_IGNOREMIMETEXTPLAIN | FMFD_URLASFILENAME, &lpMime, // result 0 // reserved ); if (SUCCEEDED (hr) && lpMime) mime = lpMime; if (mime.empty ()) { if (bytesRead >= 8 && memcmp (buffer, "\x89PNG\r\n\x1A\n", 8) == 0) mime = L"image/png"; else if (bytesRead >= 3 && buffer [0] == 0xFF && buffer [1] == 0xD8) mime = L"image/jpeg"; else if (bytesRead >= 6 && memcmp (buffer, "GIF89a", 6) == 0) mime = L"image/gif"; else if (bytesRead >= 2 && buffer [0] == 'B' && buffer [1] == 'M') mime = L"image/bmp"; else if (bytesRead >= 12 && memcmp (buffer, "RIFF", 4) == 0 && memcmp (buffer + 8, "WEBP", 4) == 0) mime = L"image/webp"; else if (bytesRead >= 4 && memcmp (buffer, "\x00\x00\x01\x00", 4) == 0) mime = L"image/x-icon"; else mime = L"application/octet-stream"; } return mime; } std::wstring GetBase64StringFromStreamW (IStream *ifile) { if (!ifile) return L""; IStream *&pStream = ifile; LARGE_INTEGER liZero = {}; pStream->Seek (liZero, STREAM_SEEK_SET, nullptr); STATSTG statstg; pStream->Stat (&statstg, STATFLAG_NONAME); ULARGE_INTEGER uliSize = statstg.cbSize; std::vector buffer (uliSize.QuadPart); ULONG bytesRead; pStream->Read (buffer.data (), static_cast (buffer.size ()), &bytesRead); DWORD base64Size = 0; if (!CryptBinaryToStringW (buffer.data (), bytesRead, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, nullptr, &base64Size)) return nullptr; std::vector base64Buffer (base64Size + 1); if (!CryptBinaryToStringW (buffer.data (), bytesRead, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, base64Buffer.data (), &base64Size)) return nullptr; pStream->Seek (liZero, STREAM_SEEK_SET, nullptr); return std::wstring (base64Buffer.data ()); } LPWSTR StreamToBase64W (_In_ HANDLE hFileStream, _Out_writes_ (dwCharCount) LPWSTR lpMimeBuf, _In_ DWORD dwCharCount, _Outptr_ LPWSTR *lpBase64Head) { IStream *ifs = (IStream *)hFileStream; if (!ifs) return nullptr; LPWSTR retptr = nullptr; std::wstring ret = L""; std::wstring mime = GetMimeTypeFromStream (ifs); auto &dwBufSize = dwCharCount; if (lpMimeBuf) { ZeroMemory (lpMimeBuf, sizeof (WCHAR) * dwBufSize); wcsncpy_s (lpMimeBuf, dwBufSize, mime.c_str (), _TRUNCATE); } ret += L"data:" + mime + L";base64,"; size_t head = ret.length (); ret += GetBase64StringFromStreamW (ifs); retptr = _wcsdup (ret.c_str ()); if (lpBase64Head) *lpBase64Head = retptr + head; return retptr; } LPWSTR GetPackagePrerequistieSystemVersionName (_In_ HPKGREAD hReader, _In_ LPCWSTR lpName) { auto ptr = ToPtrPackage (hReader); if (!ptr) return nullptr; switch (ptr->type ()) { case PackageType::single: { auto read = ptr->appx_reader (); auto pre = read.prerequisites (); auto ver = pre.get_version (lpName ? lpName : L""); auto str = GetPrerequistOSVersionDescription (ver); return _wcsdup (str.c_str ()); } break; case PackageType::bundle: { auto br = ptr->bundle_reader (); CComPtr iaf; if (FAILED (br.random_application_package (&iaf))) return nullptr; CComPtr ist; if (FAILED (iaf->GetStream (&ist))) return nullptr; CComPtr iar; if (FAILED (GetAppxPackageReader (ist, &iar))) return nullptr; appxreader read (iar.p); auto pre = read.prerequisites (); auto ver = pre.get_version (lpName ? lpName : L""); auto str = GetPrerequistOSVersionDescription (ver); return _wcsdup (str.c_str ()); } default: break; } return nullptr; } LPWSTR GetPackageCapabilityDisplayName (LPCWSTR lpCapabilityName) { if (!lpCapabilityName) return nullptr; std::wnstring capname = (lpCapabilityName ? lpCapabilityName : L""); if (capname.empty ()) return nullptr; 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); } HLIST_PVOID GetAppxBundleAllResourcePackageFileNames (_In_ HPKGREAD hReader) { auto ptr = ToPtrPackage (hReader); if (!ptr) return nullptr; if (ptr->type () == PackageType::bundle) { auto br = ptr->bundle_reader (); std::vector rpi; br.package_id_items ().resource_packages (rpi); auto buf = (HLIST_PVOID)malloc (sizeof (LIST_PVOID) + sizeof (LPWSTR) * rpi.size ()); buf->dwSize = rpi.size (); for (size_t i = 0; i < rpi.size (); i ++) { auto &it = rpi [i]; buf->alpVoid [i] = _wcsdup (it.file_name ().c_str ()); } return buf; } return nullptr; } HLIST_PVOID GetAppxBundleAllLocaleResourcePackageFileNames (_In_ HPKGREAD hReader) { auto ptr = ToPtrPackage (hReader); if (!ptr) return nullptr; if (ptr->type () == PackageType::bundle) { auto br = ptr->bundle_reader (); std::vector rpi; br.package_id_items ().resource_packages (rpi); std::vector localePkgNames; for (size_t i = 0; i < rpi.size (); i ++) { auto &it = rpi [i]; auto qres = it.qualified_resources (); std::vector langs; std::vector temp; std::vector dxt; qres.qualified_resources (&langs, &temp, &dxt); if (temp.size () > 0 || dxt.size () > 0) continue; localePkgNames.push_back (it.file_name ()); } auto buf = (HLIST_PVOID)malloc (sizeof (LIST_PVOID) + sizeof (LPWSTR) * localePkgNames.size ()); buf->dwSize = localePkgNames.size (); for (size_t i = 0; i < localePkgNames.size (); i ++) { buf->alpVoid [i] = _wcsdup (localePkgNames [i].c_str ()); } return buf; } return nullptr; } HLIST_PVOID GetAppxBundleAllFileResourcePackageFileNames (_In_ HPKGREAD hReader) { auto ptr = ToPtrPackage (hReader); if (!ptr) return nullptr; if (ptr->type () == PackageType::bundle) { auto br = ptr->bundle_reader (); std::vector rpi; br.package_id_items ().resource_packages (rpi); std::vector filePkgNames; for (size_t i = 0; i < rpi.size (); i ++) { auto &it = rpi [i]; auto qres = it.qualified_resources (); std::vector langs; std::vector temp; std::vector dxt; qres.qualified_resources (&langs, &temp, &dxt); if (temp.size () > 0) filePkgNames.push_back (it.file_name ()); } auto buf = (HLIST_PVOID)malloc (sizeof (LIST_PVOID) + sizeof (LPWSTR) * filePkgNames.size ()); buf->dwSize = filePkgNames.size (); for (size_t i = 0; i < filePkgNames.size (); i ++) { buf->alpVoid [i] = _wcsdup (filePkgNames [i].c_str ()); } return buf; } return nullptr; } void FreeAppxBundlePayloadsFileNameList (_In_ HLIST_PVOID hStringList) { if (!hStringList) return; for (size_t i = 0; i < hStringList->dwSize; i ++) { auto ptr = hStringList->alpVoid [i]; if (!ptr) continue; free (ptr); } free (hStringList); } void UpdatePackageApplicationItemGetName (_In_ LPCWSTR *lpNames, _In_ DWORD dwArrLen) { bool clearAll = !lpNames || !dwArrLen; if (clearAll) { appitems.clear (); return; } appitems.clear (); for (size_t i = 0; i < dwArrLen; i ++) { auto ptr = lpNames [i]; if (strnull (ptr)) continue; push_unique (appitems, std::wstring (ptr)); } } void GetPackageApplicationItemGetNameList (_In_ ITER_WSTRING_CALLBACK pfCallback) { if (!pfCallback) return; for (auto &it : appitems) { pfCallback (it.c_str ()); } } // ========== 以下是对清单文件的读取 ========== #define ToHandleMRead(_cpp_ptr_) reinterpret_cast (_cpp_ptr_) #define ToPtrManifest(_cpp_ptr_) reinterpret_cast (_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 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 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 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 l; auto qr = item.qualified_resources (); qr.languages (l); for (auto &it : l) push_unique (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 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 l; auto qr = item.qualified_resources (); qr.languages (l); for (auto &it : l) push_unique (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 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 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 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 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 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 caps; switch (ptr->type ()) { case PackageType::single: { auto reader = ptr->appx_reader (); auto cap = reader.capabilities (); std::vector 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 caps; switch (ptr->type ()) { case PackageType::single: { auto reader = ptr->appx_reader (); auto cap = reader.capabilities (); std::vector 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; } LPWSTR GetManifestPrerequistieSystemVersionName (_In_ HPKGMANIFESTREAD hReader, _In_ LPCWSTR lpName) { auto ptr = ToPtrManifest (hReader); if (!ptr) return nullptr; switch (ptr->type ()) { case PackageType::single: { auto read = ptr->appx_reader (); auto pre = read.prerequisites (); auto ver = pre.get_version (lpName ? lpName : L""); auto str = GetPrerequistOSVersionDescription (ver); return _wcsdup (str.c_str ()); } break; default: break; } return nullptr; } BOOL PackageReaderGetFileRoot (LPWSTR lpFilePath) { return PathRemoveFileSpecW (lpFilePath); } LPWSTR PackageReaderCombinePath (LPCWSTR lpLeft, LPCWSTR lpRight, LPWSTR lpBuf) { return PathCombineW (lpBuf, lpLeft, lpRight); } HANDLE PackageReaderGetFileStream (LPCWSTR lpFilePath) { IStream *ptr = nullptr; HRESULT hr = SHCreateStreamOnFileEx (lpFilePath, STGM_READ | STGM_SHARE_DENY_NONE, 0, FALSE, NULL, &ptr); if (SUCCEEDED (hr)) return ptr; else { if (ptr) ptr->Release (); ptr = nullptr; } return nullptr; } void PackageReaderDestroyFileStream (HANDLE hStream) { auto ptr = (IStream *)hStream; if (ptr) { ptr->Release (); return; } }