From d6d8fc5b6767ffdf17ad3d22c91ce32b8830e568 Mon Sep 17 00:00:00 2001 From: Bruce Date: Tue, 14 Oct 2025 20:42:23 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=A1=B9=E7=9B=AE=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AppInstallerReset.sln | 58 + AppInstallerReset/AppInstallerReset.vcxproj | 154 +++ .../AppInstallerReset.vcxproj.filters | 17 + dlltest/dlltest.vcxproj | 160 +++ dlltest/dlltest.vcxproj.filters | 22 + dlltest/main.cpp | 76 ++ pkgread/ReadMe.txt | 30 + pkgread/dllmain.cpp | 21 + pkgread/dynarr.h | 77 ++ pkgread/localeex.h | 163 +++ pkgread/norstr.h | 419 ++++++ pkgread/packages.config | 4 + pkgread/pkgread.cpp | 833 ++++++++++++ pkgread/pkgread.h | 293 +++++ pkgread/pkgread.vcxproj | 190 +++ pkgread/pkgread.vcxproj.filters | 72 + pkgread/raii.h | 8 + pkgread/readobj.h | 1157 +++++++++++++++++ pkgread/resource.h | 14 + pkgread/stdafx.cpp | 8 + pkgread/stdafx.h | 26 + pkgread/stringres.h | 124 ++ pkgread/syncutil.h | 124 ++ pkgread/targetver.h | 8 + pkgread/version.h | 124 ++ prireader/ReadMe.txt | 30 + prireader/dllmain.cpp | 19 + prireader/priread.h | 1 + prireader/prireader.cpp | 22 + prireader/prireader.h | 22 + prireader/prireader.vcxproj | 180 +++ prireader/prireader.vcxproj.filters | 48 + prireader/resource.h | 14 + prireader/stdafx.cpp | 8 + prireader/stdafx.h | 21 + prireader/targetver.h | 8 + 36 files changed, 4555 insertions(+) create mode 100644 AppInstallerReset.sln create mode 100644 AppInstallerReset/AppInstallerReset.vcxproj create mode 100644 AppInstallerReset/AppInstallerReset.vcxproj.filters create mode 100644 dlltest/dlltest.vcxproj create mode 100644 dlltest/dlltest.vcxproj.filters create mode 100644 dlltest/main.cpp create mode 100644 pkgread/ReadMe.txt create mode 100644 pkgread/dllmain.cpp create mode 100644 pkgread/dynarr.h create mode 100644 pkgread/localeex.h create mode 100644 pkgread/norstr.h create mode 100644 pkgread/packages.config create mode 100644 pkgread/pkgread.cpp create mode 100644 pkgread/pkgread.h create mode 100644 pkgread/pkgread.vcxproj create mode 100644 pkgread/pkgread.vcxproj.filters create mode 100644 pkgread/raii.h create mode 100644 pkgread/readobj.h create mode 100644 pkgread/resource.h create mode 100644 pkgread/stdafx.cpp create mode 100644 pkgread/stdafx.h create mode 100644 pkgread/stringres.h create mode 100644 pkgread/syncutil.h create mode 100644 pkgread/targetver.h create mode 100644 pkgread/version.h create mode 100644 prireader/ReadMe.txt create mode 100644 prireader/dllmain.cpp create mode 100644 prireader/priread.h create mode 100644 prireader/prireader.cpp create mode 100644 prireader/prireader.h create mode 100644 prireader/prireader.vcxproj create mode 100644 prireader/prireader.vcxproj.filters create mode 100644 prireader/resource.h create mode 100644 prireader/stdafx.cpp create mode 100644 prireader/stdafx.h create mode 100644 prireader/targetver.h diff --git a/AppInstallerReset.sln b/AppInstallerReset.sln new file mode 100644 index 0000000..321a35f --- /dev/null +++ b/AppInstallerReset.sln @@ -0,0 +1,58 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "appinstaller", "AppInstallerReset\AppInstallerReset.vcxproj", "{C96219BE-8AFF-4914-8933-B6B7047A94D8}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pkgread", "pkgread\pkgread.vcxproj", "{A7753282-AA16-43D9-8ACA-7065239DD702}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "prireader", "prireader\prireader.vcxproj", "{D8CFAA98-0A77-4C5B-A61B-11EF44206712}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dlltest", "dlltest\dlltest.vcxproj", "{F5CCB3AB-AC43-432A-862D-4F264760B09B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C96219BE-8AFF-4914-8933-B6B7047A94D8}.Debug|x64.ActiveCfg = Debug|x64 + {C96219BE-8AFF-4914-8933-B6B7047A94D8}.Debug|x64.Build.0 = Debug|x64 + {C96219BE-8AFF-4914-8933-B6B7047A94D8}.Debug|x86.ActiveCfg = Debug|Win32 + {C96219BE-8AFF-4914-8933-B6B7047A94D8}.Debug|x86.Build.0 = Debug|Win32 + {C96219BE-8AFF-4914-8933-B6B7047A94D8}.Release|x64.ActiveCfg = Release|x64 + {C96219BE-8AFF-4914-8933-B6B7047A94D8}.Release|x64.Build.0 = Release|x64 + {C96219BE-8AFF-4914-8933-B6B7047A94D8}.Release|x86.ActiveCfg = Release|Win32 + {C96219BE-8AFF-4914-8933-B6B7047A94D8}.Release|x86.Build.0 = Release|Win32 + {A7753282-AA16-43D9-8ACA-7065239DD702}.Debug|x64.ActiveCfg = Debug|x64 + {A7753282-AA16-43D9-8ACA-7065239DD702}.Debug|x64.Build.0 = Debug|x64 + {A7753282-AA16-43D9-8ACA-7065239DD702}.Debug|x86.ActiveCfg = Debug|Win32 + {A7753282-AA16-43D9-8ACA-7065239DD702}.Debug|x86.Build.0 = Debug|Win32 + {A7753282-AA16-43D9-8ACA-7065239DD702}.Release|x64.ActiveCfg = Release|x64 + {A7753282-AA16-43D9-8ACA-7065239DD702}.Release|x64.Build.0 = Release|x64 + {A7753282-AA16-43D9-8ACA-7065239DD702}.Release|x86.ActiveCfg = Release|Win32 + {A7753282-AA16-43D9-8ACA-7065239DD702}.Release|x86.Build.0 = Release|Win32 + {D8CFAA98-0A77-4C5B-A61B-11EF44206712}.Debug|x64.ActiveCfg = Debug|x64 + {D8CFAA98-0A77-4C5B-A61B-11EF44206712}.Debug|x64.Build.0 = Debug|x64 + {D8CFAA98-0A77-4C5B-A61B-11EF44206712}.Debug|x86.ActiveCfg = Debug|Win32 + {D8CFAA98-0A77-4C5B-A61B-11EF44206712}.Debug|x86.Build.0 = Debug|Win32 + {D8CFAA98-0A77-4C5B-A61B-11EF44206712}.Release|x64.ActiveCfg = Release|x64 + {D8CFAA98-0A77-4C5B-A61B-11EF44206712}.Release|x64.Build.0 = Release|x64 + {D8CFAA98-0A77-4C5B-A61B-11EF44206712}.Release|x86.ActiveCfg = Release|Win32 + {D8CFAA98-0A77-4C5B-A61B-11EF44206712}.Release|x86.Build.0 = Release|Win32 + {F5CCB3AB-AC43-432A-862D-4F264760B09B}.Debug|x64.ActiveCfg = Debug|x64 + {F5CCB3AB-AC43-432A-862D-4F264760B09B}.Debug|x64.Build.0 = Debug|x64 + {F5CCB3AB-AC43-432A-862D-4F264760B09B}.Debug|x86.ActiveCfg = Debug|Win32 + {F5CCB3AB-AC43-432A-862D-4F264760B09B}.Debug|x86.Build.0 = Debug|Win32 + {F5CCB3AB-AC43-432A-862D-4F264760B09B}.Release|x64.ActiveCfg = Release|x64 + {F5CCB3AB-AC43-432A-862D-4F264760B09B}.Release|x64.Build.0 = Release|x64 + {F5CCB3AB-AC43-432A-862D-4F264760B09B}.Release|x86.ActiveCfg = Release|Win32 + {F5CCB3AB-AC43-432A-862D-4F264760B09B}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/AppInstallerReset/AppInstallerReset.vcxproj b/AppInstallerReset/AppInstallerReset.vcxproj new file mode 100644 index 0000000..0ce832c --- /dev/null +++ b/AppInstallerReset/AppInstallerReset.vcxproj @@ -0,0 +1,154 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {C96219BE-8AFF-4914-8933-B6B7047A94D8} + Win32Proj + AppInstallerReset + 8.1 + appinstaller + + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + + + Windows + true + + + + + + + Level3 + Disabled + _DEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + + + Windows + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + + + + + + + + \ No newline at end of file diff --git a/AppInstallerReset/AppInstallerReset.vcxproj.filters b/AppInstallerReset/AppInstallerReset.vcxproj.filters new file mode 100644 index 0000000..03c8628 --- /dev/null +++ b/AppInstallerReset/AppInstallerReset.vcxproj.filters @@ -0,0 +1,17 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + \ No newline at end of file diff --git a/dlltest/dlltest.vcxproj b/dlltest/dlltest.vcxproj new file mode 100644 index 0000000..1c8879e --- /dev/null +++ b/dlltest/dlltest.vcxproj @@ -0,0 +1,160 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {F5CCB3AB-AC43-432A-862D-4F264760B09B} + Win32Proj + dlltest + 8.1 + + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + + + Level3 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + $(OutDir)pkgread.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + {a7753282-aa16-43d9-8aca-7065239dd702} + + + + + + + + + \ No newline at end of file diff --git a/dlltest/dlltest.vcxproj.filters b/dlltest/dlltest.vcxproj.filters new file mode 100644 index 0000000..203a71c --- /dev/null +++ b/dlltest/dlltest.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + 源文件 + + + \ No newline at end of file diff --git a/dlltest/main.cpp b/dlltest/main.cpp new file mode 100644 index 0000000..01cdc79 --- /dev/null +++ b/dlltest/main.cpp @@ -0,0 +1,76 @@ +#include +#include "..\pkgread\pkgread.h" +#include +#include + +int main (int argc, char *argv []) +{ + // 1. Reader + HPKGREAD hReader = CreatePackageReader (); + if (!hReader) { + std::wcerr << L"CreatePackageReader failed!" << std::endl; + return 1; + } + std::wcout << L"CreatePackageReader succeeded!" << std::endl; + + // 2. ذļ + std::wcout << L"Please enter the file path: " << std::endl; + std::wcout << L"\\> "; + std::wstring pkgPathStr; + std::getline (std::wcin, pkgPathStr); + if (!pkgPathStr.empty () && pkgPathStr.front () == L'\"' && pkgPathStr.back () == L'\"' && pkgPathStr.size () >= 2) { + pkgPathStr = pkgPathStr.substr (1, pkgPathStr.size () - 2); + } + LPCWSTR pkgPath = pkgPathStr.c_str (); + if (!LoadPackageFromFile (hReader, pkgPath)) { + std::wcerr << L"LoadPackageFromFile failed for " << pkgPath << std::endl; + DestroyPackageReader (hReader); + return 1; + } + std::wcout << L"LoadPackageFromFile succeeded!" << std::endl; + + // 3. ֤ + WORD type = GetPackageType (hReader); + std::wcout << L"Package Type: " << type << std::endl; + + // 4. ֤Ч + BOOL valid = IsPackageValid (hReader); + std::wcout << L"IsPackageValid: " << (valid ? L"True" : L"False") << std::endl; + + // 5. ȡ + LPWSTR pkgName = GetPackageIdentityStringValue (hReader, PKG_IDENTITY_NAME); + if (pkgName) + std::wcout << L"Package Name: " << pkgName << std::endl; + else + std::wcerr << L"GetPackageIdentityStringValue PKG_IDENTITY_NAME failed!" << std::endl; + + // 6. ȡ汾 + VERSION ver; + if (GetPackageIdentityVersion (hReader, &ver, FALSE)) { + std::wcout << L"Package Version: " << ver.major << L"." << ver.minor << L"." << ver.build << L"." << ver.revision << std::endl; + } + else { + std::wcerr << L"GetPackageIdentityVersion failed!" << std::endl; + } + + // 7. о Application + HLIST_PVOID appList = GetAllApplicationItemsName (); + if (appList) { + std::wcout << L"Application Count: " << appList->dwSize << std::endl; + for (DWORD i = 0; i < appList->dwSize; ++i) { + LPCWSTR appName = (LPCWSTR)appList->alpVoid [i]; + if (appName) + std::wcout << L"App[" << i << L"]: " << appName << std::endl; + } + DestroyApplicationItemsName (appList); + } + else { + std::wcerr << L"GetAllApplicationItemsName failed!" << std::endl; + } + + // 8. + DestroyPackageReader (hReader); + + system ("pause"); + return 0; +} \ No newline at end of file diff --git a/pkgread/ReadMe.txt b/pkgread/ReadMe.txt new file mode 100644 index 0000000..4439f92 --- /dev/null +++ b/pkgread/ReadMe.txt @@ -0,0 +1,30 @@ +======================================================================== + 动态链接库:pkgread 项目概述 +======================================================================== + +应用程序向导已为您创建了此 pkgread DLL。 + +本文件概要介绍组成 pkgread 应用程序的每个文件的内容。 + + +pkgread.vcxproj + 这是使用应用程序向导生成的 VC++ 项目的主项目文件,其中包含生成该文件的 Visual C++ 的版本信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。 + +pkgread.vcxproj.filters + 这是使用“应用程序向导”生成的 VC++ 项目筛选器文件。它包含有关项目文件与筛选器之间的关联信息。在 IDE 中,通过这种关联,在特定节点下以分组形式显示具有相似扩展名的文件。例如,“.cpp”文件与“源文件”筛选器关联。 + +pkgread.cpp + 这是主 DLL 源文件。 + +///////////////////////////////////////////////////////////////////////////// +其他标准文件: + +StdAfx.h, StdAfx.cpp + 这些文件用于生成名为 pkgread.pch 的预编译头 (PCH) 文件和名为 StdAfx.obj 的预编译类型文件。 + +///////////////////////////////////////////////////////////////////////////// +其他注释: + +应用程序向导使用“TODO:”注释来指示应添加或自定义的源代码部分。 + +///////////////////////////////////////////////////////////////////////////// diff --git a/pkgread/dllmain.cpp b/pkgread/dllmain.cpp new file mode 100644 index 0000000..16b23e9 --- /dev/null +++ b/pkgread/dllmain.cpp @@ -0,0 +1,21 @@ +// dllmain.cpp : DLL Ӧóڵ㡣 +#include "stdafx.h" + +BOOL APIENTRY DllMain( HMODULE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + case DLL_THREAD_ATTACH: + CoInitializeEx (NULL, COINIT_MULTITHREADED); break; + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + CoUninitialize (); + break; + } + return TRUE; +} + diff --git a/pkgread/dynarr.h b/pkgread/dynarr.h new file mode 100644 index 0000000..7e69982 --- /dev/null +++ b/pkgread/dynarr.h @@ -0,0 +1,77 @@ +#pragma once +#include +#include +#include + +template bool compare_default (const T &l, const T &r) { return l == r; } +template bool find_vec (std::vector &vec, const T &value, const std::function &callback, std::function compare = compare_default , bool sorted = false) +{ + const size_t n = vec.size (); + if (!compare) compare = compare_default; + if (sorted) + { + size_t left = 0, right = n; + while (left < right) + { + size_t mid = left + (right - left) / 2; + if (compare (vec [mid], value)) + { + callback (mid); + return true; + } + if (vec [mid] < value) left = mid + 1; + else right = mid; + } + return false; + } + if (n < 64) + { + for (size_t i = 0; i < n; i++) + { + if (compare (vec [i], value)) + { + callback (i); + return true; + } + } + return false; + } + const size_t blockSize = 8; + size_t i = 0; + for (; i + blockSize <= n; i += blockSize) + { + for (size_t j = 0; j < blockSize; j ++) + { + if (compare (vec [i + j], value)) + { + callback (i + j); + return true; + } + } + } + for (; i < n; i ++) + { + if (compare (vec [i], value)) + { + callback (i); + return true; + } + } + return false; +} +template void push_unique (std::vector &vec, const T &value, std::function compare = compare_default ) +{ + bool found = find_vec ( + vec, value, + [] (size_t) {}, + compare); + if (!found) vec.push_back (value); +} +template void push_normal (std::vector &vec, const T &value) +{ + vec.push_back (value); +} +template void push_normal (std::vector &target, const std::vector &another) +{ + target.insert (target.end (), another.begin (), another.end ()); +} \ No newline at end of file diff --git a/pkgread/localeex.h b/pkgread/localeex.h new file mode 100644 index 0000000..b528d56 --- /dev/null +++ b/pkgread/localeex.h @@ -0,0 +1,163 @@ +#pragma once +#include +#include +static std::wstring StringToWString (const std::string &str, UINT codePage = CP_ACP) +{ + if (str.empty ()) return std::wstring (); + int len = MultiByteToWideChar (codePage, 0, str.c_str (), -1, nullptr, 0); + if (len == 0) return std::wstring (); + std::wstring wstr (len - 1, L'\0'); + MultiByteToWideChar (codePage, 0, str.c_str (), -1, &wstr [0], len); + return wstr; +} + +#undef GetLocaleInfo +std::string GetLocaleInfoA (LCID code, LCTYPE type) +{ + char buf [LOCALE_NAME_MAX_LENGTH] = {0}; + GetLocaleInfoA (code, type, buf, LOCALE_NAME_MAX_LENGTH); + return buf; +} +std::wstring GetLocaleInfoW (LCID code, LCTYPE type) +{ + WCHAR buf [LOCALE_NAME_MAX_LENGTH] = {0}; + GetLocaleInfoW (code, type, buf, LOCALE_NAME_MAX_LENGTH); + return buf; +} +void GetLocaleInfo (LCID code, LCTYPE type, std::wstring &output) +{ + output = GetLocaleInfoW (code, type); +} +void GetLocaleInfo (LCID code, LCTYPE type, std::string &output) +{ + output = GetLocaleInfoA (code, type); +} +int GetLocaleInfoEx (std::wstring lpLocaleName, LCTYPE type, std::wstring &output) +{ + WCHAR buf [LOCALE_NAME_MAX_LENGTH] = {0}; + int res = GetLocaleInfoEx (lpLocaleName.c_str (), type, buf, LOCALE_NAME_MAX_LENGTH); + if (&output) output = std::wstring (buf); + return res; +} + +#undef SetLocaleInfo +BOOL SetLocaleInfoA (LCID code, LCTYPE type, const std::string &lcData) +{ + return SetLocaleInfoA (code, type, lcData.c_str ()); +} +BOOL SetLocaleInfoW (LCID code, LCTYPE type, const std::wstring &lcData) +{ + return SetLocaleInfoW (code, type, lcData.c_str ()); +} +BOOL SetLocaleInfo (LCID code, LCTYPE type, const std::wstring &lcData) +{ + return SetLocaleInfoW (code, type, lcData); +} +BOOL SetLocaleInfo (LCID code, LCTYPE type, const std::string &lcData) +{ + return SetLocaleInfoA (code, type, lcData); +} + +std::string GetLocaleRestrictedCodeFromLcidA (LCID lcid) +{ + return GetLocaleInfoA (lcid, 89); +} +std::wstring GetLocaleRestrictedCodeFromLcidW (LCID lcid) +{ + return GetLocaleInfoW (lcid, 89); +} +void GetLocaleRestrictedCodeFromLcid (LCID lcid, std::string &ret) +{ + ret = GetLocaleRestrictedCodeFromLcidA (lcid); +} +void GetLocaleRestrictedCodeFromLcid (LCID lcid, std::wstring &ret) +{ + ret = GetLocaleRestrictedCodeFromLcidW (lcid); +} + +std::string GetLocaleElaboratedCodeFromLcidA (LCID lcid) +{ + return GetLocaleInfoA (lcid, 90); +} +std::wstring GetLocaleElaboratedCodeFromLcidW (LCID lcid) +{ + return GetLocaleInfoW (lcid, 90); +} +void GetLocaleElaboratedCodeFromLcid (LCID lcid, std::wstring &ret) +{ + ret = GetLocaleElaboratedCodeFromLcidW (lcid); +} +void GetLocaleElaboratedCodeFromLcid (LCID lcid, std::string &ret) +{ + ret = GetLocaleElaboratedCodeFromLcidA (lcid); +} + +LCID LocaleCodeToLcidW (LPCWSTR localeCode) +{ + BYTE buf [LOCALE_NAME_MAX_LENGTH * sizeof (WCHAR)] = {0}; + int res = GetLocaleInfoEx (localeCode, LOCALE_RETURN_NUMBER | LOCALE_ILANGUAGE, (LPWSTR)buf, LOCALE_NAME_MAX_LENGTH); + LCID lcid = *((LCID *)buf); + return lcid; +} +LCID LocaleCodeToLcidA (LPCSTR localeCode) +{ + std::wstring lcWide = StringToWString (std::string (localeCode)); + return LocaleCodeToLcidW (lcWide.c_str ()); +} +LCID LocaleCodeToLcid (const std::wstring &loccode) +{ + return LocaleCodeToLcidW (loccode.c_str ()); +} +LCID LocaleCodeToLcid (const std::string &loccode) +{ + return LocaleCodeToLcidA (loccode.c_str ()); +} + +std::string GetLocaleRestrictedCodeA (LPCSTR lc) +{ + return GetLocaleInfoA (LocaleCodeToLcidA (lc), 89); +} +std::string GetLocaleRestrictedCodeA (const std::string &lc) +{ + return GetLocaleInfoA (LocaleCodeToLcidA (lc.c_str ()), 89); +} +std::wstring GetLocaleRestrictedCodeW (LPCWSTR lc) +{ + return GetLocaleInfoW (LocaleCodeToLcidW (lc), 89); +} +std::wstring GetLocaleRestrictedCodeW (const std::wstring &lc) +{ + return GetLocaleInfoW (LocaleCodeToLcidW (lc.c_str ()), 89); +} +std::wstring GetLocaleRestrictedCode (const std::wstring &lc) { return GetLocaleRestrictedCodeW (lc); } +std::string GetLocaleRestrictedCode (const std::string &lc) { return GetLocaleRestrictedCodeA (lc); } + +std::string GetLocaleElaboratedCodeA (LPCSTR lc) +{ + return GetLocaleInfoA (LocaleCodeToLcidA (lc), 90); +} +std::string GetLocaleElaboratedCodeA (const std::string &lc) +{ + return GetLocaleInfoA (LocaleCodeToLcidA (lc.c_str ()), 90); +} +std::wstring GetLocaleElaboratedCodeW (LPCWSTR lc) +{ + return GetLocaleInfoW (LocaleCodeToLcidW (lc), 90); +} +std::wstring GetLocaleElaboratedCodeW (const std::wstring &lc) +{ + return GetLocaleInfoW (LocaleCodeToLcidW (lc.c_str ()), 90); +} +std::wstring GetLocaleElaboratedCode (const std::wstring &lc) { return GetLocaleElaboratedCodeW (lc); } +std::string GetLocaleElaboratedCode (const std::string &lc) { return GetLocaleElaboratedCodeA (lc); } + +std::string LcidToLocaleCodeA (LCID lcid, char divide = '-') +{ + return GetLocaleRestrictedCodeFromLcidA (lcid) + divide + GetLocaleElaboratedCodeFromLcidA (lcid); +} +std::wstring LcidToLocaleCodeW (LCID lcid, WCHAR divide = L'-') +{ + return GetLocaleRestrictedCodeFromLcidW (lcid) + divide + GetLocaleElaboratedCodeFromLcidW (lcid); +} +std::wstring LcidToLocaleCode (LCID lcid, WCHAR divide = L'-') { return LcidToLocaleCodeW (lcid, divide); } +std::string LcidToLocaleCode (LCID lcid, char divide = '-') { return LcidToLocaleCodeA (lcid, divide); } \ No newline at end of file diff --git a/pkgread/norstr.h b/pkgread/norstr.h new file mode 100644 index 0000000..53c1a24 --- /dev/null +++ b/pkgread/norstr.h @@ -0,0 +1,419 @@ +#pragma once +#include +#include +#include +namespace l0km +{ + template , typename AL = std::allocator > inline std::basic_string toupper (const std::basic_string &src) + { + std::basic_string dst = src; + static const std::locale loc; + const std::ctype &ctype = std::use_facet > (loc); + for (typename std::basic_string ::size_type i = 0; i < src.size (); ++ i) + { + dst [i] = ctype.toupper (src [i]); + } + return dst; + } + template , typename AL = std::allocator > inline std::basic_string tolower (const std::basic_string &src) + { + std::basic_string dst = src; + static const std::locale loc; + const std::ctype &ctype = std::use_facet > (loc); + for (typename std::basic_string ::size_type i = 0; i < src.size (); ++ i) + { + dst [i] = ctype.tolower (src [i]); + } + return dst; + } + inline char toupper (char ch) + { + static const std::locale loc; + return std::use_facet > (loc).toupper (ch); + } + inline char tolower (char ch) + { + static const std::locale loc; + return std::use_facet > (loc).tolower (ch); + } + inline wchar_t toupper (wchar_t ch) + { + static const std::locale loc; + return std::use_facet > (loc).toupper (ch); + } + inline wchar_t tolower (wchar_t ch) + { + static const std::locale loc; + return std::use_facet > (loc).tolower (ch); + } + inline int toupper (int ch) + { + static const std::locale loc; + return std::use_facet > (loc).toupper (ch); + } + inline int tolower (int ch) + { + static const std::locale loc; + return std::use_facet > (loc).tolower (ch); + } +} +template bool is_blank (ct &ch) +{ + return ch == ct (' ') || ch == ct ('\t') || ch == ct ('\n'); +} +template , typename AL = std::allocator > std::basic_string NormalizeString (const std::basic_string &str, bool upper = false, bool includemidblank = false) +{ + typedef std::basic_string string_type; + string_type result; + if (str.empty ()) return result; + auto begin_it = str.begin (); + auto end_it = str.end (); + while (begin_it != end_it && is_blank (*begin_it)) ++begin_it; + while (end_it != begin_it && is_blank (*(end_it - 1))) --end_it; + bool in_space = false; + for (auto it = begin_it; it != end_it; ++ it) + { + if (is_blank (*it)) + { + if (includemidblank) + { + if (!in_space) + { + result.push_back (E (' ')); + in_space = true; + } + } + else + { + result.push_back (*it); + in_space = true; + } + } + else + { + result.push_back (*it); + in_space = false; + } + } + if (upper) return l0km::toupper (result); + else return l0km::tolower (result); +} +template , typename AL = std::allocator > bool IsNormalizeStringEquals (const std::basic_string &l, const std::basic_string &r, bool includemidblank = false) +{ + auto skip_blank = [&] (auto &it, auto &end) + { + while (it != end && is_blank (*it)) ++ it; + }; + auto it_l = l.begin (), it_r = r.begin (); + auto end_l = l.end (), end_r = r.end (); + skip_blank (it_l, end_l); + skip_blank (it_r, end_r); + while (it_l != end_l && it_r != end_r) + { + E ch_l = *it_l; + E ch_r = *it_r; + ch_l = l0km::tolower (ch_l); + ch_r = l0km::tolower (ch_r); + if (ch_l != ch_r) return false; + ++ it_l; + ++ it_r; + if (includemidblank) + { + if (is_blank (ch_l)) + { + skip_blank (it_l, end_l); + skip_blank (it_r, end_r); + } + } + } + skip_blank (it_l, end_l); + skip_blank (it_r, end_r); + return it_l == end_l && it_r == end_r; +} +template , typename AL = std::allocator > int64_t NormalizeStringCompare (const std::basic_string &l, const std::basic_string &r, bool includemidblank = false) +{ + auto skip_blank = [&] (auto &it, auto &end) + { + while (it != end && is_blank (*it)) ++ it; + }; + auto it_l = l.begin (), it_r = r.begin (); + auto end_l = l.end (), end_r = r.end (); + skip_blank (it_l, end_l); + skip_blank (it_r, end_r); + while (it_l != end_l && it_r != end_r) + { + E ch_l = l0km::tolower (*it_l); + E ch_r = l0km::tolower (*it_r); + if (ch_l != ch_r) return ch_l < ch_r ? -1 : 1; + ++ it_l; + ++ it_r; + if (includemidblank) + { + if (is_blank (*it_l) || is_blank (*it_r)) + { + skip_blank (it_l, end_l); + skip_blank (it_r, end_r); + if (it_l != end_l && it_r != end_r) + { + ch_l = l0km::tolower (*it_l); + ch_r = l0km::tolower (*it_r); + } + } + } + } + skip_blank (it_l, end_l); + skip_blank (it_r, end_r); + if (it_l == end_l && it_r == end_r) return 0; + if (it_l == end_l) return -1; + return 1; +} +template bool IsNormalizeStringEquals (const CharT *l, const CharT *r, bool includemidblank = false) +{ + if (!l || !r) return l == r; + auto skip_blank = [] (const CharT *&p) + { + while (*p && is_blank (*p)) ++ p; + }; + const CharT *p1 = l; + const CharT *p2 = r; + skip_blank (p1); + skip_blank (p2); + while (*p1 && *p2) + { + CharT ch1 = l0km::tolower (*p1); + CharT ch2 = l0km::tolower (*p2); + if (ch1 != ch2) return false; + ++ p1; + ++ p2; + if (includemidblank) + { + if (is_blank (*p1) || is_blank (*p2)) + { + skip_blank (p1); + skip_blank (p2); + } + } + } + skip_blank (p1); + skip_blank (p2); + return *p1 == 0 && *p2 == 0; +} +template int64_t NormalizeStringCompare (const CharT *l, const CharT *r, bool includemidblank = false) +{ + if (!l || !r) return l ? 1 : (r ? -1 : 0); + auto skip_blank = [] (const CharT *&p) + { + while (*p && is_blank (*p)) ++ p; + }; + const CharT *p1 = l; + const CharT *p2 = r; + skip_blank (p1); + skip_blank (p2); + while (*p1 && *p2) + { + CharT ch1 = l0km::tolower (*p1); + CharT ch2 = l0km::tolower (*p2); + if (ch1 != ch2) return (ch1 < ch2) ? -1 : 1; + ++ p1; + ++ p2; + if (includemidblank) + { + if (is_blank (*p1) || is_blank (*p2)) + { + skip_blank (p1); + skip_blank (p2); + } + } + } + skip_blank (p1); + skip_blank (p2); + if (*p1 == 0 && *p2 == 0) return 0; + if (*p1 == 0) return -1; + return 1; +} +template , typename AL = std::allocator > bool IsNormalizeStringEmpty (const std::basic_string &str) +{ + return IsNormalizeStringEquals (str, std::basic_string ()); +} +template , typename AL = std::allocator > std::basic_string StringTrim (const std::basic_string &str, bool includemidblank = false) +{ + typedef std::basic_string string_type; + typedef typename string_type::size_type size_type; + if (str.empty ()) return string_type (); + size_type first = 0; + size_type last = str.size (); + while (first < last && is_blank (str [first])) ++first; + while (last > first && is_blank (str [last - 1])) --last; + if (first == last) return string_type (); + string_type result; + result.reserve (last - first); + bool in_space = false; + for (size_type i = first; i < last; ++ i) + { + if (is_blank (str [i])) + { + if (includemidblank) + { + if (!in_space) + { + result.push_back (E (' ')); + in_space = true; + } + } + else + { + result.push_back (str [i]); + in_space = true; + } + } + else + { + result.push_back (str [i]); + in_space = false; + } + } + return result; +} +template , typename AL = std::allocator > size_t GetNormalizeStringLength (const std::basic_string &str, bool includemidblank = false) +{ + typedef typename std::basic_string ::size_type size_type; + if (str.empty ()) return 0; + size_type first = 0, last = str.size (); + while (first < last && is_blank (str [first])) ++first; + while (last > first && is_blank (str [last - 1])) --last; + if (first == last) return 0; + size_t length = 0; + bool in_space = false; + for (size_type i = first; i < last; ++i) + { + if (is_blank (str [i])) + { + if (includemidblank) + { + if (!in_space) + { + ++ length; + in_space = true; + } + } + else + { + ++ length; + in_space = true; + } + } + else + { + ++ length; + in_space = false; + } + } + return length; +} +namespace std +{ + + template , typename al = std::allocator > class basic_nstring: public std::basic_string + { + using base = std::basic_string ; + bool default_upper = false, default_include_blank_in_str = false; + public: + using typename base::size_type; + using typename base::value_type; + using base::base; + basic_nstring (): base (), default_upper (false), default_include_blank_in_str (false) {} + basic_nstring (const ct *pStr): base (pStr), default_upper (false), default_include_blank_in_str (false) {} + basic_nstring (const base &str): base (str) {} + basic_nstring (base &&str): base (std::move (str)) {} + bool upper_default () const { return this->default_upper; } + bool upper_default (bool value) { return this->default_upper = value; } + bool include_blank_in_str_middle () const { return this->default_include_blank_in_str; } + bool include_blank_in_str_middle (bool value) { return this->default_include_blank_in_str = value; } + base normalize (bool upper, bool includemidblank) const + { + return NormalizeString (*this, upper, includemidblank); + } + base normalize (bool upper) const + { + return this->normalize (upper, default_include_blank_in_str); + } + base normalize () const { return this->normalize (default_upper); } + base upper (bool includemidblank) const + { + return NormalizeString (*this, true, includemidblank); + } + base upper () const { return this->upper (default_include_blank_in_str); } + base lower (bool includemidblank) const + { + return NormalizeString (*this, false, includemidblank); + } + base lower () const { return this->lower (default_include_blank_in_str); } + base trim (bool includemidblank) const + { + return StringTrim (*this, includemidblank); + } + base trim () const { return this->trim (default_include_blank_in_str); } + size_t length (bool includemidblank) const { return GetNormalizeStringLength (*this, includemidblank); } + size_t length () const { return length (default_include_blank_in_str); } + bool empty () const + { + return IsNormalizeStringEmpty (*this); + } + bool equals (const base &another, bool includemidblank) const + { + return IsNormalizeStringEquals (*this, another, includemidblank); + } + bool equals (const base &another) const { return equals (another, default_include_blank_in_str); } + int64_t compare (const base &another, bool includemidblank) const + { + return NormalizeStringCompare (*this, another, includemidblank); + } + int64_t compare (const base &another) const { return compare (another, default_include_blank_in_str); } + base &string () { return *this; } + base to_string (bool upper, bool includemidblank) const { return this->normalize (upper, includemidblank); } + base to_string (bool upper) const { return this->normalize (upper, default_include_blank_in_str); } + base to_string () const { return this->normalize (default_upper); } + bool operator == (const base &other) const { return equals (other, false); } + bool operator != (const base &other) const { return !equals (other, false); } + bool operator < (const base &other) const { return compare (other, false) < 0; } + bool operator > (const base &other) const { return compare (other, false) > 0; } + bool operator <= (const base &other) const { return compare (other, false) <= 0; } + bool operator >= (const base &other) const { return compare (other, false) >= 0; } + int64_t operator - (const base &other) const { return compare (other, false); } + template , typename AL = std::allocator > + static bool equals (const std::basic_string &l, const std::basic_string &r, bool remove_mid_blank = false) + { + return IsNormalizeStringEquals (l, r, remove_mid_blank); + } + template , typename AL = std::allocator > + static int64_t compare (const std::basic_string &l, const std::basic_string &r, bool remove_mid_blank = false) + { + return NormalizeStringCompare (l, r, remove_mid_blank); + } + template , typename AL = std::allocator > + static std::basic_string normalize (const std::basic_string &str, bool to_upper = false, bool remove_mid_blank = false) + { + return NormalizeString (str, to_upper, remove_mid_blank); + } + template , typename AL = std::allocator > + static std::basic_string trim (const std::basic_string &str, bool remove_mid_blank = false) + { + return StringTrim (str, remove_mid_blank); + } + template , typename AL = std::allocator > + static size_t length (const std::basic_string &str, bool remove_mid_blank = false) + { + return GetNormalizeStringLength (str, remove_mid_blank); + } + template , typename AL = std::allocator > + static bool empty (const std::basic_string &str) + { + return IsNormalizeStringEmpty (str); + } + template , typename AL = std::allocator > + static std::basic_nstring to_nstring (std::basic_string &str) { return std::basic_nstring (str); } + }; + + typedef basic_nstring nstring; + typedef basic_nstring wnstring; +} \ No newline at end of file diff --git a/pkgread/packages.config b/pkgread/packages.config new file mode 100644 index 0000000..a7a422e --- /dev/null +++ b/pkgread/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/pkgread/pkgread.cpp b/pkgread/pkgread.cpp new file mode 100644 index 0000000..d41959c --- /dev/null +++ b/pkgread/pkgread.cpp @@ -0,0 +1,833 @@ +// pkgread.cpp : DLL Ӧóĵ +// + +#include "stdafx.h" +#include "readobj.h" +#include "pkgread.h" +#include "localeex.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); +} diff --git a/pkgread/pkgread.h b/pkgread/pkgread.h new file mode 100644 index 0000000..81c55b8 --- /dev/null +++ b/pkgread/pkgread.h @@ -0,0 +1,293 @@ +// ifdef Ǵʹ DLL 򵥵 +// ı׼ DLL еļ϶ PKGREAD_EXPORTS +// űġʹô DLL +// κĿϲӦ˷šԴļаļκĿὫ +// PKGREAD_API ΪǴ DLL ģ DLL ô˺궨 +// ΪDZġ +#ifndef _APPX_PACKAGE_READER_H_ +#define _APPX_PACKAGE_READER_H_ +#ifdef PKGREAD_EXPORTS +#define PKGREAD_API __declspec(dllexport) +#else +#define PKGREAD_API __declspec(dllimport) +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif +#ifdef __cplusplus +#define _DEFAULT_INIT_VALUE_(_init_value_) = _init_value_ + #ifdef PKGREAD_EXPORTS + #define _DEFAULT_INIT_VALUE_FORFUNC_(_init_value_) = _init_value_ + #else + #define _DEFAULT_INIT_VALUE_FORFUNC_(_init_value_) + #endif +#else +#define _DEFAULT_INIT_VALUE_(_init_value_) +#define _DEFAULT_INIT_VALUE_FORFUNC_(_init_value_) +#endif + +#ifndef _TYPE_STRUCT_VERSION_ +#define _TYPE_STRUCT_VERSION_ + typedef struct _VERSION + { + #if defined (__cplusplus) && defined (PKGREAD_EXPORTS) + _VERSION (UINT16 major = 0, UINT16 minor = 0, UINT16 build = 0, UINT16 revision = 0): + major (major), minor (minor), build (build), revision (revision) {} + #endif + UINT16 major _DEFAULT_INIT_VALUE_ (0), + minor _DEFAULT_INIT_VALUE_ (0), + build _DEFAULT_INIT_VALUE_ (0), + revision _DEFAULT_INIT_VALUE_ (0); + } VERSION; +#endif + +#ifndef _TYPE_STRUCT_LIST_PVOID_ +#define _TYPE_STRUCT_LIST_PVOID_ + typedef struct _LIST_PVOID + { + DWORD dwSize _DEFAULT_INIT_VALUE_ (0); + LPVOID alpVoid [1] _DEFAULT_INIT_VALUE_ ({NULL}); + } LIST_PVOID, *HLIST_PVOID; +#endif + +#ifndef _TYPE_STRUCT_PAIR_PVOID_ +#define _TYPE_STRUCT_PAIR_PVOID_ + typedef struct _PAIR_PVOID_ + { + LPVOID lpKey _DEFAULT_INIT_VALUE_ (NULL); + LPVOID lpValue _DEFAULT_INIT_VALUE_ (NULL); + } PAIR_PVOID, *HPAIR_PVOID; +#endif + +#define TEMPLATE_STRUCT(_typename_) typedef struct _typename_##__ _typename_ + TEMPLATE_STRUCT (PKGREADER); + typedef PKGREADER *HPKGREAD; + TEMPLATE_STRUCT (APPENUMERATOR); + typedef APPENUMERATOR *HAPPENUMERATOR; + +#define PKGTYPE_UNKNOWN 0 +#define PKGTYPE_APPX 1 +#define PKGTYPE_BUNDLE 2 +#define PKGROLE_UNKNOWN 0 +#define PKGROLE_APPLICATION 1 +#define PKGROLE_FRAMEWORK 2 +#define PKGROLE_RESOURCE 3 +// ȡ + PKGREAD_API HPKGREAD CreatePackageReader (); + // ͨȡ򿪰 + PKGREAD_API BOOL LoadPackageFromFile (_In_ HPKGREAD hReader, _In_ LPCWSTR lpFilePath); + // ٰȡ룩 + PKGREAD_API void DestroyPackageReader (_In_ HPKGREAD hReader); + // ȡͣAppx AppxBundle PKGTYPE_* + PKGREAD_API WORD GetPackageType (_In_ HPKGREAD hReader); + // ذǷЧЧİ᷵ؼ١ + PKGREAD_API BOOL IsPackageValid (_In_ HPKGREAD hReader); + // ȡͣӦðܰԴ + // AppxBundle ԶԴΪܰ޷ AppxBundleԴӦðһͬ AppxBundle + // PKGROLE_* ꡣ + PKGREAD_API WORD GetPackageRole (_In_ HPKGREAD hReader); + + // Identity + // AppxBundle ˵AppxBundle 봢 Appx İϢһ£һڰ汾źʹܹϣ +#define PKG_IDENTITY_BUNDLE_GETAPPXINFO ((PKGTYPE_BUNDLE && 0xFFFF) << 16) +#define PKG_IDENTITY_NAME 0 +#define PKG_IDENTITY_PUBLISHER 1 +#define PKG_IDENTITY_PACKAGEFAMILYNAME 2 +#define PKG_IDENTITY_PACKAGEFULLNAME 3 +#define PKG_IDENTITY_RESOURCEID 4 +#define PKG_ARCHITECTURE_UNKNOWN 0x0 +#define PKG_ARCHITECTURE_X86 0x1 +#define PKG_ARCHITECTURE_X64 0x2 +#define PKG_ARCHITECTURE_ARM 0x4 +#define PKG_ARCHITECTURE_ARM64 0x8 +#define PKG_ARCHITECTURE_NEUTRAL 0xF + // ȡϢܻȡıֵ֧ PKG_IDENTITY_* ǰ׺ĺ NAME, PUBLISHER, PACKAGEFAMILYNAME, PACKAGEFULLNAME, RESOURCEID + // PKG_IDENTITY_BUNDLE_GETAPPXINFO ͨλʱȡ AppxBundle ijһӦð + PKGREAD_API LPWSTR GetPackageIdentityStringValue (_In_ HPKGREAD hReader, _In_ DWORD dwName); + // ȡϢ bGetSubPkgVer Ϊ棬Ҵ򿪵İΪ AppxBundle AppxBundle еijӦðİ汾š + PKGREAD_API BOOL GetPackageIdentityVersion (_In_ HPKGREAD hReader, _Out_ VERSION *pVersion, _In_ BOOL bGetSubPkgVer _DEFAULT_INIT_VALUE_FORFUNC_ (0)); + // AppxBundle ֵ PKG_IDENTITY_BUNDLE_GETAPPXINFO򷵻һλֵ 0b0011ζ֧ x86 x64 + PKGREAD_API BOOL GetPackageIdentityArchitecture (_In_ HPKGREAD hReader, _Out_ DWORD *pdwArchi); + + // Properties + // ȡֵַ +#define PKG_PROPERTIES_DISPLAYNAME L"DisplayName" +#define PKG_PROPERTIES_DESCRIPTION L"Description" +#define PKG_PROPERTIES_LOGO L"Logo" +#define PKG_PROPERTIES_PUBLISHER L"PublisherDisplayName" +// ȡ߼ֵ +#define PKG_PROPERTIES_FRAMEWORD L"Framework" +#define PKG_PROPERTIES_IS_RESOURCE L"ResourcePackage" + // οhttps://learn.microsoft.com/en-us/windows/win32/api/appxpackaging/nf-appxpackaging-iappxmanifestproperties-getstringvalue + // ʹú PKG_PROPERTIES_* ǰ׺ DISPLAYNAME, DESCRIPTION, LOGO, PUBLISHER + PKGREAD_API LPWSTR GetPackagePropertiesStringValue (_In_ HPKGREAD hReader, _In_ LPCWSTR lpName); + // οhttps://learn.microsoft.com/zh-cn/windows/win32/api/appxpackaging/nf-appxpackaging-iappxmanifestproperties-getboolvalue + // ʹú PKG_PROPERTIES_* ǰ׺ FRAMEWORD, IS_RESOURCE (Windows 8.1 ֧) + PKGREAD_API HRESULT GetPackagePropertiesBoolValue (_In_ HPKGREAD hReader, _In_ LPCWSTR lpName, _Outptr_ BOOL *pRet); +// Applications + // ע⣺ڶȡ Application ڹٷ API öֻͣöһΡ + // ԤȰźҪϢöʱл档 + // ӺɾοЩhttps://learn.microsoft.com/en-us/windows/win32/api/appxpackaging/nf-appxpackaging-iappxmanifestapplication-getstringvalue + // DLL ֧֣Id, DisplayName, BackgroundColor, ForegroundText, ShortName, Square44x44Logo + PKGREAD_API BOOL AddPackageApplicationItemGetName (_In_ LPCWSTR lpName); + // ƳҪϢ + PKGREAD_API BOOL RemovePackageApplicationItemGetName (_In_ LPCWSTR lpName); + // ȡеϢȡʱָijԱתΪ LPCWSTR ȡҲ޸ġ + // ע⣺ص HLIST_PVOID Ҫ DestroyApplicationItemsName ١ + PKGREAD_API HLIST_PVOID GetAllApplicationItemsName (); + // ͨ GetAllApplicationItemsName ȡ HLIST_PVOID DestroyApplicationItemsName ١ + PKGREAD_API void DestroyApplicationItemsName (_In_ HLIST_PVOID hList); + // ȡ Application ϢöԼϢǰҪ٣ֱҲҪ١ + // ͨ GetPackageApplications ȡ HAPPENUMERATOR DestroyApplicationsMap + PKGREAD_API HAPPENUMERATOR GetPackageApplications (_In_ HPKGREAD hReader); + // Application öת HLIST_PVOID { HLIST_PVOID {HPAIR_PVOID} } ڶӳɵ飩 + // ȡָԱתΪ LPCWSTR ȡ LPCWSTR HAPPENUMERATOR ڶ + PKGREAD_API HLIST_PVOID ApplicationsToMap (_In_ HAPPENUMERATOR hEnumerator); + // ͨ ApplicationsToMap ȡ HLIST_PVOID DestroyApplicationsMap + PKGREAD_API void DestroyApplicationsMap (_In_ HLIST_PVOID hEnumerator); + // ͨ GetPackageApplications ȡ HAPPENUMERATOR DestroyApplicationsMap + PKGREAD_API void DestroyPackageApplications (_In_ HAPPENUMERATOR hEnumerator); + + // Resources +#ifndef _TYPE_STRUCT_LIST_LCID_ +#define _TYPE_STRUCT_LIST_LCID_ + typedef struct _LIST_LCID + { + DWORD dwSize _DEFAULT_INIT_VALUE_ (0); + LCID aLcid [1] _DEFAULT_INIT_VALUE_ ({0}); + } LIST_LCID, *HLIST_LCID; +#endif +#ifndef _TYPE_STRUCT_LIST_UINT32_ +#define _TYPE_STRUCT_LIST_UINT32_ + typedef struct _LIST_UINT32 + { + DWORD dwSize _DEFAULT_INIT_VALUE_ (0); + LCID aUI32 [1] _DEFAULT_INIT_VALUE_ ({0}); + } LIST_UINT32, *HLIST_UINT32; +#endif + // (Locale Code) 顣 LPWSTR ȡעһҪͨ DestroyResourcesLanguagesList ͷ + PKGREAD_API HLIST_PVOID GetResourcesLanguages (_In_ HPKGREAD hReader); + // ؽת LCID en-US Ϊ 1033zh-CN Ϊ 2052 顣 UINT32 ȡ + // עһҪͨ DestroyResourcesLanguagesLcidList ͷ + PKGREAD_API HLIST_LCID GetResourcesLanguagesToLcid (_In_ HPKGREAD hReader); + // DPI ֧֣ 100125 顣 + // עһҪͨ DestroyResourcesScalesList ꣨ DestroyUInt32List ͷ + PKGREAD_API HLIST_UINT32 GetResourcesScales (_In_ HPKGREAD hReader); +#define PKG_RESOURCES_DXFEATURE_LEVEL9 0x1 +#define PKG_RESOURCES_DXFEATURE_LEVEL10 0x2 +#define PKG_RESOURCES_DXFEATURE_LEVEL11 0x4 +#define PKG_RESOURCES_DXFEATURE_LEVEL12 0x8 +#define PKG_RESOURCES_DXFEATURE_UNSPECIFIED 0 + // һ DWORD ֵͨλȡֵ֧ DirectX ֧֡ 0 ζŶֵ֧֡ͷš + PKGREAD_API DWORD GetResourcesDxFeatureLevels (_In_ HPKGREAD hReader); + // GetResourcesLanguages ȡ + PKGREAD_API void DestroyResourcesLanguagesList (_In_ HLIST_PVOID hList); + // GetResourcesLanguagesToLcid ȡ + PKGREAD_API void DestroyResourcesLanguagesLcidList (_In_ HLIST_LCID hList); + PKGREAD_API void DestroyUInt32List (_In_ HLIST_UINT32 hList); + // GetResourcesScales ȡ +#define DestroyResourcesScalesList DestroyUInt32List + + // Dependencies +#ifndef _TYPE_STRUCT_DEPENDENCY_ +#define _TYPE_STRUCT_DEPENDENCY_ + typedef struct _DEPENDENCY_INFO + { + VERSION verMin; + LPWSTR lpName _DEFAULT_INIT_VALUE_ (NULL); + LPWSTR lpPublisher _DEFAULT_INIT_VALUE_ (NULL); + } DEPENDENCY_INFO; +#endif +#ifndef _TYPE_STRUCT_DEPENDENCY_LIST_ +#define _TYPE_STRUCT_DEPENDENCY_LIST_ + typedef struct _LIST_DEPINFO + { + DWORD dwSize _DEFAULT_INIT_VALUE_ (0); + DEPENDENCY_INFO aDepInfo [1]; + } LIST_DEPINFO, *HLIST_DEPINFO; +#endif + // ȡϢ飬 HLIST_DEPINFO DestroyDependencesInfoList + PKGREAD_API HLIST_DEPINFO GetDependencesInfoList (_In_ HPKGREAD hReader); + // ͨ GetDependencesInfoList صָɴ + PKGREAD_API void DestroyDependencesInfoList (_In_ HLIST_DEPINFO hList); + + // Capabilities + PKGREAD_API HLIST_PVOID GetCapabilitiesList (_In_ HPKGREAD hReader); + PKGREAD_API HLIST_PVOID GetDeviceCapabilitiesList (_In_ HPKGREAD hReader); + PKGREAD_API void DestroyWStringList (_In_ HLIST_PVOID hList); +#define DestroyCapabilitiesList DestroyWStringList +#define DestroyDeviceCapabilitiesList DestroyWStringList + +#if defined (__cplusplus) && defined (PKGREAD_EXPORTS) +#include +#include +#include + class package_info + { + private: + HPKGREAD hReader = nullptr; + std::wstring filepath = L""; + struct deconstr + { + std::function endtask = nullptr; + deconstr (std::function pf): endtask (pf) {} + ~deconstr () { if (endtask) endtask (); } + }; + public: + class identity + { + private: + HPKGREAD &hReader; + public: + identity (HPKGREAD hReader): hReader (hReader) {} + std::wstring string_value (DWORD dwName) const + { + LPWSTR lpstr = nullptr; + deconstr rel ([&lpstr] () { + if (lpstr) free (lpstr); + lpstr = nullptr; + }); + lpstr = GetPackageIdentityStringValue (hReader, dwName); + return lpstr; + } + VERSION version (bool read_subpkg_ver = false) const + { + VERSION ver; + GetPackageIdentityVersion (hReader, &ver, read_subpkg_ver); + return ver; + } + DWORD architecture () const + { + DWORD dw = 0; + GetPackageIdentityArchitecture (hReader, &dw); + return dw; + } + }; + package_info (): hReader (CreatePackageReader ()) {} + ~package_info () { DestroyPackageReader (hReader); hReader = nullptr; } + std::wstring file () const { return filepath; } + bool file (const std::wstring &path) + { + return LoadPackageFromFile (hReader, (filepath = path).c_str ()); + } + WORD package_type () const { return GetPackageType (hReader); } + bool valid () const { return hReader && IsPackageValid (hReader); } + WORD package_role () const { return GetPackageRole (hReader); } + identity get_identity () const { return identity (hReader); } + + }; +#endif + +#ifdef _DEFAULT_INIT_VALUE_ +#undef _DEFAULT_INIT_VALUE_ +#endif +#ifdef _DEFAULT_INIT_VALUE_FORFUNC_ +#undef _DEFAULT_INIT_VALUE_FORFUNC_ +#endif +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/pkgread/pkgread.vcxproj b/pkgread/pkgread.vcxproj new file mode 100644 index 0000000..9d84c81 --- /dev/null +++ b/pkgread/pkgread.vcxproj @@ -0,0 +1,190 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {A7753282-AA16-43D9-8ACA-7065239DD702} + Win32Proj + pkgread + 8.1 + + + + DynamicLibrary + true + v140 + Unicode + + + DynamicLibrary + false + v140 + true + Unicode + + + DynamicLibrary + true + v140 + Unicode + + + DynamicLibrary + false + v140 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;PKGREAD_EXPORTS;%(PreprocessorDefinitions) + true + + + Windows + true + + + + + Use + Level3 + Disabled + _DEBUG;_WINDOWS;_USRDLL;PKGREAD_EXPORTS;%(PreprocessorDefinitions) + true + + + Windows + true + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;PKGREAD_EXPORTS;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + + + + + Level3 + Use + MaxSpeed + true + true + NDEBUG;_WINDOWS;_USRDLL;PKGREAD_EXPORTS;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + + + + + + + + + + + + + + + + + + + + + + false + + + false + + + false + + + false + + + + + + Create + Create + Create + Create + + + + + + + + + \ No newline at end of file diff --git a/pkgread/pkgread.vcxproj.filters b/pkgread/pkgread.vcxproj.filters new file mode 100644 index 0000000..10f25bd --- /dev/null +++ b/pkgread/pkgread.vcxproj.filters @@ -0,0 +1,72 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + + + 源文件 + + + 源文件 + + + 源文件 + + + + + + \ No newline at end of file diff --git a/pkgread/raii.h b/pkgread/raii.h new file mode 100644 index 0000000..cc82c4f --- /dev/null +++ b/pkgread/raii.h @@ -0,0 +1,8 @@ +#pragma once +#include +struct raii +{ + std::function endtask = nullptr; + raii (std::function pFunc = nullptr): endtask (pFunc) {} + ~raii () { if (endtask) endtask (); } +}; \ No newline at end of file diff --git a/pkgread/readobj.h b/pkgread/readobj.h new file mode 100644 index 0000000..a73e1ff --- /dev/null +++ b/pkgread/readobj.h @@ -0,0 +1,1157 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dynarr.h" +#include "version.h" +#include "stringres.h" +#include "norstr.h" +#include "raii.h" + +bool IsFileExistsW (LPCWSTR filename) +{ + DWORD dwAttrib = GetFileAttributesW (filename); + return (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)); +} +bool IsFileExistsA (LPCSTR filename) +{ + DWORD dwAttrib = GetFileAttributesA (filename); + return (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)); +} +bool IsFileExists (LPWSTR filePath) { return IsFileExistsW (filePath); } +bool IsFileExists (LPCSTR filePath) { return IsFileExistsA (filePath); } +bool IsFileExists (std::string filePath) { return IsFileExistsA (filePath.c_str ()); } +bool IsFileExists (std::wstring filePath) { return IsFileExistsW (filePath.c_str ()); } + +HRESULT GetBundleReader (_In_ LPCWSTR inputFileName, _Outptr_ IAppxBundleReader** bundleReader) +{ + if (bundleReader == NULL) return E_POINTER; + *bundleReader = NULL; + HRESULT hr = S_OK; + CComPtr appxBundleFactory; + CComPtr inputStream; + hr = CoCreateInstance (__uuidof(AppxBundleFactory), NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS (&appxBundleFactory)); + if (FAILED (hr)) return hr; + hr = SHCreateStreamOnFileEx (inputFileName, STGM_READ | STGM_SHARE_DENY_NONE, 0, FALSE, NULL, &inputStream); + if (FAILED (hr)) return hr; + hr = appxBundleFactory->CreateBundleReader (inputStream, bundleReader); + return hr; +} +HRESULT GetPackageReader (_In_ LPCWSTR inputFileName, _Outptr_ IAppxPackageReader **reader) +{ + if (reader == NULL) return E_POINTER; + *reader = NULL; + HRESULT hr = S_OK; + CComPtr appxFactory; + CComPtr inputStream; + hr = CoCreateInstance (__uuidof(AppxFactory), NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS (&appxFactory)); + if (FAILED (hr)) return hr; + hr = SHCreateStreamOnFileEx (inputFileName, STGM_READ | STGM_SHARE_DENY_NONE, 0, FALSE, NULL, &inputStream); + if (FAILED (hr)) return hr; + hr = appxFactory->CreatePackageReader (inputStream, reader); + return hr; +} +HRESULT GetAppxPackageReader (_In_ IStream *inputStream, _Outptr_ IAppxPackageReader **packageReader) +{ + HRESULT hr = S_OK; + CComPtr appxFactory = NULL; + hr = CoCreateInstance (__uuidof (AppxFactory), NULL, CLSCTX_INPROC_SERVER, __uuidof (IAppxFactory), (LPVOID *)(&appxFactory)); + if (SUCCEEDED (hr)) hr = appxFactory->CreatePackageReader (inputStream, packageReader); + return hr; +} +HRESULT GetAppxManifestReader2 (IAppxManifestReader *m, IAppxManifestReader2 **m2) +{ + if (!m | !m2) return E_FAIL; + return m->QueryInterface (__uuidof (IAppxManifestReader2), (void **)m2); +} + +class app_info: public std::map +{ + using Base = std::map ; + public: + using Base::Base; + std::wstring user_model_id () const { return this->find (L"AppUserModelID")->second; } + friend bool operator == (const app_info &a1, const app_info &a2) { return std::wnstring (a1.user_model_id ()) == std::wnstring (a2.user_model_id ()); } + friend bool operator != (const app_info &a1, const app_info &a2) { return std::wnstring (a1.user_model_id ()) != std::wnstring (a2.user_model_id ()); } + explicit operator bool () const { return std::wnstring::to_nstring (this->user_model_id ()).empty (); } +}; + +class dep_info +{ + public: + std::wstring name = L""; + std::wstring publisher = L""; + version minversion; + dep_info (const std::wstring &name, const std::wstring &publisher, version versionLimit): + name (std::wnstring::trim (name)), publisher (std::wnstring::trim (publisher)), minversion (versionLimit) {} + dep_info (IAppxManifestPackageDependency *&dependency) + { + LPWSTR lpName = nullptr, lpPublisher = nullptr; + UINT64 u64Ver = 0; + raii rel ([&lpName, &lpPublisher] () -> void { + if (lpName) CoTaskMemFree (lpName); + if (lpPublisher) CoTaskMemFree (lpPublisher); + }); + if (SUCCEEDED (dependency->GetName (&lpName)) && lpName) name += lpName; + if (SUCCEEDED (dependency->GetPublisher (&lpPublisher)) && lpPublisher) publisher += lpPublisher; + if (SUCCEEDED (dependency->GetMinVersion (&u64Ver))) minversion = u64Ver; + } + dep_info () {} + bool operator == (const dep_info &another) { return std::wnstring (this->name) == std::wnstring (another.name); } + bool empty () { return std::wnstring (name).empty (); } +}; + +template RetType process_default (GetType &g) +{ + return RetType (g); +} +template > +size_t EnumerateComInterface (EnumerationType *iEnum, RetVectorType &retarr, std::function process = process_default ) +{ + BOOL hasCurrent; + HRESULT hr = iEnum->GetHasCurrent (&hasCurrent); + if (SUCCEEDED (hr) && hasCurrent) retarr.reserve (8); + while (SUCCEEDED (hr) && hasCurrent) + { + GetType value; + hr = iEnum->GetCurrent (&value); + if (SUCCEEDED (hr)) + { + try + { + push_normal (retarr, process (value)); + } + catch (const std::exception &e) {} + } + hr = iEnum->MoveNext (&hasCurrent); + } + return retarr.size (); +} +template bool is_data_valid_default (T &data) { return true; } + +enum class PackageType: UINT8 +{ + unknown = 0, // δ֪ҲЧ + single = 1, // Appx + bundle = 2 // AppxBundle +}; +enum class PackageRole: UINT8 +{ + unknown = 0, // δ֪ + application = 1, // ӦðװΪеİ + framework = 2, // ܰװΪ + resource = 3 // ԴΪӦðṩԵԴ +}; +template class com_info +{ + private: + CComPtr icom = nullptr; + protected: + ComInterface *pointer () const noexcept { return icom; } + void attach (ComInterface *ptr) { icom.Attach (ptr); } + void set (ComInterface *ptr) { icom = ptr; } + template std::wstring get (_In_ Fn func) const + { + if (!icom) return L""; + LPWSTR lpstr = nullptr; + raii task ([&lpstr] () { + if (lpstr) CoTaskMemFree (lpstr); + lpstr = nullptr; + }); + return (SUCCEEDED ((icom->*func)(&lpstr)) && lpstr) ? std::wstring (lpstr) : L""; + } + template RetType get (_In_ Fn func, _In_ std::function process = process_default ) const + { + if (!icom) return RetType (); + GetType value {}; + if (SUCCEEDED ((icom->*func) (&value))) return process (value); + else return RetType (); + } + template size_t enumerate (_In_ Fn func, _Out_ std::vector &output) const + { + output.clear (); + if (!icom) return 0; + CComPtr ienum; + if (FAILED ((icom->*func) (&ienum))) return 0; + return EnumerateComInterface (ienum, output, [] (LPWSTR &lpstr) -> std::wstring { + raii reltask ([&lpstr] () { if (lpstr) { CoTaskMemFree (lpstr); lpstr = nullptr; } }); + return std::wstring (lpstr ? lpstr : L""); + }); + } + template , typename Fn> size_t enumerate (_In_ Fn func, _Out_ RetVectorType &output, _In_ std::function process = process_default ) const + { + output.clear (); + if (!icom) return 0; + CComPtr ienum; + if (FAILED (icom->*func (&ienum)) || !ienum) return 0; + return EnumerateComInterface (ienum, output, process); + } + public: + using Interface = ComInterface; + explicit com_info (ComInterface *ptr) { icom.Attach (ptr); } + com_info (const com_info &) = delete; + com_info &operator = (const com_info &) = delete; + com_info (com_info &&) noexcept = default; + com_info &operator = (com_info &&) noexcept = default; + bool valid () const { return !!icom; } +}; +template class com_info_quote +{ + using IComInterface = ComInterface *; + private: + IComInterface &icom = nullptr; + protected: + ComInterface *pointer () const noexcept { return icom; } + template std::wstring get (_In_ Fn func) const + { + if (!icom) return L""; + LPWSTR lpstr = nullptr; + raii task ([&lpstr] () { + if (lpstr) CoTaskMemFree (lpstr); + lpstr = nullptr; + }); + return (SUCCEEDED ((icom->*func)(&lpstr)) && lpstr) ? std::wstring (lpstr) : L""; + } + template RetType get (_In_ Fn func, _In_ std::function process = process_default ) const + { + if (!icom) return RetType (); + GetType value {}; + if (SUCCEEDED ((icom->*func) (&value))) return process (value); + else return RetType (); + } + template size_t enumerate (_In_ Fn func, _Out_ std::vector &output) const + { + output.clear (); + if (!icom) return 0; + CComPtr ienum; + if (FAILED ((icom->*func) (&ienum))) return 0; + return EnumerateComInterface (ienum, output, [] (LPWSTR &lpstr) -> std::wstring { + raii reltask ([&lpstr] () { if (lpstr) { CoTaskMemFree (lpstr); lpstr = nullptr; } }); + return std::wstring (lpstr ? lpstr : L""); + }); + } + template , typename Fn> size_t enumerate (_In_ Fn func, _Out_ RetVectorType &output, _In_ std::function process = process_default ) const + { + output.clear (); + if (!icom) return 0; + CComPtr ienum; + if (FAILED (icom->*func (&ienum)) || !ienum) return 0; + return EnumerateComInterface (ienum, output, process); + } + public: + using Interface = ComInterface; + explicit com_info_quote (IComInterface &ptr): icom (ptr) {} + com_info_quote (const com_info_quote &) = delete; + com_info_quote &operator = (const com_info_quote &) = delete; + com_info_quote (com_info_quote &&) noexcept = default; + com_info_quote &operator = (com_info_quote &&) noexcept = default; + bool valid () const { return !!icom; } +}; +namespace appx_info +{ + class appx_id: virtual public com_info + { + using Base = com_info ; + public: + using Base::Base; + std::wstring name () const { return get (&Interface::GetName); } + std::wstring publisher () const { return get (&Interface::GetPublisher); } + std::wstring package_family_name () const { return get (&Interface::GetPackageFamilyName); } + std::wstring package_full_name () const { return get (&Interface::GetPackageFullName); } + std::wstring resource_id () const { return get (&Interface::GetResourceId); } + version version () const { return get (&Interface::GetVersion); } + APPX_PACKAGE_ARCHITECTURE architecture () const { return get (&Interface::GetArchitecture); } + bool publisher_compare (const std::wstring &another) const + { + BOOL ret = FALSE; + return (SUCCEEDED (pointer ()->ComparePublisher (another.c_str (), &ret)) ? ret != FALSE : false); + } + }; + class appx_qres: virtual public com_info + { + using Base = com_info ; + public: + using Base::Base; + size_t enumerate (_In_ std::function callback) const + { + size_t cnt = 0; + BOOL hasCurrent = FALSE; + HRESULT hr = pointer ()->GetHasCurrent (&hasCurrent); + while (SUCCEEDED (hr) && hasCurrent) + { + CComPtr qres; + hr = pointer ()->GetCurrent (&qres); + if (SUCCEEDED (hr)) + { + cnt ++; + callback (qres); + } + hr = pointer ()->MoveNext (&hasCurrent); + } + return cnt; + } + size_t qualified_resources ( + _Out_ std::vector *languages = nullptr, + _Out_ std::vector *scales = nullptr, + _Out_ std::vector *dxlevels = nullptr + ) const + { + if (languages) languages->clear (); + if (scales) scales->clear (); + if (dxlevels) dxlevels->clear (); + return enumerate ([&languages, &scales, &dxlevels] (IAppxManifestQualifiedResource *qr) { + LPWSTR lpstr = nullptr; + raii endt ([&lpstr] () { + if (lpstr) CoTaskMemFree (lpstr); + lpstr = nullptr; + }); + UINT32 u32 = 0; + DX_FEATURE_LEVEL dx = DX_FEATURE_LEVEL::DX_FEATURE_LEVEL_UNSPECIFIED; + if (SUCCEEDED (qr->GetLanguage (&lpstr)) && lpstr && languages) languages->push_back (lpstr); + else if (SUCCEEDED (qr->GetScale (&u32)) && u32 && scales) scales->push_back (u32); + else if (SUCCEEDED (qr->GetDXFeatureLevel (&dx)) && dx != DX_FEATURE_LEVEL::DX_FEATURE_LEVEL_UNSPECIFIED && dxlevels) dxlevels->push_back (dx); + }); + } + size_t languages (_Out_ std::vector &languages) const { return qualified_resources (&languages); } + size_t languages (_Out_ std::vector &output) const + { + output.clear (); + BOOL hasCurrent = false; + HRESULT hr = pointer ()->GetHasCurrent (&hasCurrent); + while (SUCCEEDED (hr) && hasCurrent) + { + CComPtr qr; + hr = pointer ()->GetCurrent (&qr); + if (SUCCEEDED (hr)) + { + LPWSTR lpstr = nullptr; + raii endt ([&lpstr] () { + if (lpstr) CoTaskMemFree (lpstr); + lpstr = nullptr; + }); + hr = qr->GetLanguage (&lpstr); + if (SUCCEEDED (hr) && lpstr) push_unique (output, std::wnstring (lpstr)); + } + hr = pointer ()->MoveNext (&hasCurrent); + } + return output.size (); + } + size_t scales (_Out_ std::vector &scales) const { return qualified_resources (nullptr, &scales); } + size_t dx_feature_level (_Out_ std::vector &dxlevels) const { return qualified_resources (nullptr, nullptr, &dxlevels); } + }; + class appx_res: virtual public com_info + { + using Base = com_info ; + public: + using Base::Base; + appx_res (IAppxManifestReader *ptr = nullptr): com_info (nullptr) { set (ptr); } + size_t languages (_Out_ std::vector &output) const + { + output.clear (); + return enumerate (&Interface::GetResources, output); + } + size_t languages (_Out_ std::vector &output) const + { + output.clear (); + BOOL hasCurrent = false; + CComPtr re; + HRESULT hr = pointer ()->GetResources (&re); + if (FAILED (hr)) return false; + hr = re->GetHasCurrent (&hasCurrent); + while (SUCCEEDED (hr) && hasCurrent) + { + LPWSTR lpstr = nullptr; + raii endt ([&lpstr] () { + if (lpstr) CoTaskMemFree (lpstr); + lpstr = nullptr; + }); + hr = re->GetCurrent (&lpstr); + if (SUCCEEDED (hr) && lpstr) + { + push_unique (output, std::wnstring (lpstr)); + } + hr = re->MoveNext (&hasCurrent); + } + return output.size (); + } + size_t scales (_Out_ std::vector &scales) const + { + return qualified_resources (&IAppxManifestQualifiedResource::GetScale, scales, [] (UINT32 &v) -> bool { + return v != 0; + }); + } + size_t dx_feature_level (_Out_ std::vector &dxlevels) const + { + return qualified_resources (&IAppxManifestQualifiedResource::GetDXFeatureLevel, dxlevels, [] (DX_FEATURE_LEVEL &v) -> bool { + return v != DX_FEATURE_LEVEL::DX_FEATURE_LEVEL_UNSPECIFIED; + }); + } + appx_qres to_qualified_resources () const + { + CComPtr m2; + IAppxManifestQualifiedResourcesEnumerator *ip = nullptr; + if (SUCCEEDED (GetAppxManifestReader2 (pointer (), &m2))) m2->GetQualifiedResources (&ip); + return appx_qres (ip); + } + private: + template > + size_t qualified_resources (_In_ Fn func, _Out_ Vector &output, _In_ std::function valid = is_data_valid_default , _In_ std::function process = process_default ) const + { + output.clear (); + CComPtr m2; + if (FAILED (GetAppxManifestReader2 (pointer (), &m2))) return 0; + CComPtr e; + if (FAILED (m2->GetQualifiedResources (&e))) return 0; + BOOL hasCurrent = false; + HRESULT hr = e->GetHasCurrent (&hasCurrent); + while (SUCCEEDED (hr) && hasCurrent) + { + CComPtr res; + if (SUCCEEDED (e->GetCurrent (&res))) + { + GetValue value; + hr = (res->*func) (&value); + if (SUCCEEDED (hr) && valid (value)) + { + output.push_back (process (value)); + } + } + hr = e->MoveNext (&hasCurrent); + } + return output.size (); + } + size_t qualified_resources (_Out_ std::vector &languages, _Out_ std::vector &scales, _Out_ std::vector &dxlevels) + { + languages.clear (); + scales.clear (); + dxlevels.clear (); + size_t cnt = 0; + CComPtr m2; + if (FAILED (GetAppxManifestReader2 (pointer (), &m2))) return 0; + CComPtr e; + if (FAILED (m2->GetQualifiedResources (&e))) return 0; + BOOL hasCurrent = false; + HRESULT hr = e->GetHasCurrent (&hasCurrent); + while (SUCCEEDED (hr) && hasCurrent) + { + CComPtr res; + if (SUCCEEDED (e->GetCurrent (&res))) + { + LPWSTR lpstr = nullptr; + raii endt ([&lpstr] () { + if (lpstr) CoTaskMemFree (lpstr); + lpstr = nullptr; + }); + UINT32 scale = 0; + DX_FEATURE_LEVEL dx = DX_FEATURE_LEVEL::DX_FEATURE_LEVEL_UNSPECIFIED; + if (SUCCEEDED (res->GetLanguage (&lpstr)) && lpstr) + { + push_unique (languages, std::wstring (lpstr), [] (const std::wstring &v1, const std::wstring &v2) -> bool { + return std::wnstring (v1) == std::wnstring (v2); + }); + } + if (SUCCEEDED (res->GetScale (&scale)) && scale) + { + push_unique (scales, scale); + } + if (SUCCEEDED (res->GetDXFeatureLevel (&dx)) && dx != DX_FEATURE_LEVEL::DX_FEATURE_LEVEL_UNSPECIFIED) + { + push_unique (dxlevels, dx); + } + cnt ++; + } + hr = e->MoveNext (&hasCurrent); + } + return cnt; + } + }; + class appx_prop: virtual public com_info + { + using Base = com_info ; + public: + using Base::Base; + std::wstring string_value (const std::wstring &name) const + { + LPWSTR lpstr = nullptr; + raii endt ([&lpstr] () { + if (lpstr) CoTaskMemFree (lpstr); + lpstr = nullptr; + }); + HRESULT hr = pointer ()->GetStringValue (name.c_str (), &lpstr); + if (SUCCEEDED (hr) && lpstr) return std::wstring () + lpstr; + return L""; + } + bool bool_value (const std::wstring &name) const + { + BOOL boolvalue = FALSE; + HRESULT hr = pointer ()->GetBoolValue (name.c_str (), &boolvalue); + if (SUCCEEDED (hr)) return boolvalue != FALSE; + return FALSE; + } + std::wstring display_name () const { return string_value (L"DisplayName"); } + std::wstring description () const { return string_value (L"Description"); } + std::wstring publisher () const { return string_value (L"PublisherDisplayName"); } + std::wstring logo () const { return string_value (L"Logo"); } + // жǷΪܰ/п⣩ + bool framework () const { return bool_value (L"Framework"); } + // жǷΪԴ + bool resource_package () const { return bool_value (L"ResourcePackage"); } + }; + class appx_preq: virtual public com_info + { + using Base = com_info ; + public: + using Base::Base; + appx_preq (IAppxManifestReader *ptr = nullptr): com_info (nullptr) { set (ptr); } + version os_min_version () const { return get_version (L"OSMinVersion"); } + version os_max_version_tested () const { return get_version (L"OSMaxVersionTested"); } + private: + version get_version (const std::wstring &name) const + { + UINT64 u64 = 0; + if (SUCCEEDED (pointer ()->GetPrerequisite (name.c_str (), &u64))) return version (u64); + return version (); + } + }; + class appx_apps: virtual public com_info + { + using Base = com_info ; + public: + using Base::Base; + size_t applications (_Out_ std::vector &output) const + { + return EnumerateComInterface (pointer (), output, [] (IAppxManifestApplication *&p) -> app_info { + raii rel ([&p] () { + if (p) p->Release (); + p = nullptr; + }); + app_info app; + LPWSTR userid; + { + raii endt ([&userid] () { + if (userid) CoTaskMemFree (userid); + userid = nullptr; + }); + if (SUCCEEDED (p->GetAppUserModelId (&userid))) + { + app [L"AppUserModelID"] = userid; + } + } + for (auto &it : GetApplicationAttributeItems ()) + { + LPWSTR lpstr; + raii endt1 ([&lpstr] () { + if (lpstr) CoTaskMemFree (lpstr); + lpstr = nullptr; + }); + if (SUCCEEDED (p->GetStringValue (it.c_str (), &lpstr))) app [it] = lpstr; + else app [it] = nullptr; + } + return app; + }); + } + size_t app_user_model_ids (_Out_ std::vector &output) const + { + return EnumerateComInterface (pointer (), output, [] (IAppxManifestApplication *&p) -> std::wstring { + raii rel ([&p] () { + if (p) p->Release (); + p = nullptr; + }); + LPWSTR userid; + raii endt ([&userid] () { + if (userid) CoTaskMemFree (userid); + userid = nullptr; + }); + if (SUCCEEDED (p->GetAppUserModelId (&userid))) return userid; + else return L""; + }); + } + size_t string_values (_In_ const std::wstring &name, _Out_ std::vector &output) const + { + return EnumerateComInterface (pointer (), output, [&name] (IAppxManifestApplication *&p) -> std::wstring { + raii rel ([&p] () { + if (p) p->Release (); + p = nullptr; + }); + LPWSTR str = nullptr; + raii endt ([&str] () { + if (str) CoTaskMemFree (str); + str = nullptr; + }); + if (SUCCEEDED (p->GetStringValue (name.c_str (), &str))) return std::wstring (str); + else return L""; + }); + } + size_t id_s (_Out_ std::vector &output) const { return string_values (L"Id", output); } + size_t visualelements_displaynames (_Out_ std::vector &output) const { return string_values (L"DisplayName", output); } + size_t visualelements_backgroundcolors (_Out_ std::vector &output) const { return string_values (L"BackgroundColor", output); } + size_t visualelements_foregroundcolors (_Out_ std::vector &output) const { return string_values (L"ForegroundText", output); } + size_t visualelements_shortnames (_Out_ std::vector &output) const { return string_values (L"ShortName", output); } + size_t visualelements_44x44logos (_Out_ std::vector &output) const { return string_values (L"Square44x44Logo", output); } + size_t size () const + { + size_t cnt = 0; + BOOL hasCurrent = FALSE; + HRESULT hr = pointer ()->GetHasCurrent (&hasCurrent); + while (SUCCEEDED (hr) && hasCurrent) + { + hr = pointer ()->GetHasCurrent (&hasCurrent); + if (SUCCEEDED (hr) && hasCurrent) cnt ++; + hr = pointer ()->MoveNext (&hasCurrent); + } + return cnt; + } + }; + class appx_capabs: virtual public com_info + { + using Base = com_info ; + APPX_CAPABILITIES cflags; + public: + using Base::Base; + appx_capabs (IAppxManifestDeviceCapabilitiesEnumerator *devicec, APPX_CAPABILITIES capa): cflags (capa), com_info (devicec) {} + appx_capabs () = default; + APPX_CAPABILITIES capabilities () const { return cflags; } + size_t device_capabilities (_Out_ std::vector &output) const + { + return EnumerateComInterface (pointer (), output, [] (LPWSTR &lp) { + raii ([&lp] () { + if (lp) CoTaskMemFree (lp); + lp = nullptr; + }); + return lp ? lp : L""; + }); + } + // ӹܰλת + size_t capabilities_names (_Out_ std::vector &output) const + { + output.clear (); + CapabilitiesFlagsToNames (cflags, output); + return output.size (); + } + // ȡܺ豸ܵй + size_t all_capabilities (_Out_ std::vector &output) const + { + output.clear (); + std::vector devs; + device_capabilities (devs); + capabilities_names (output); + for (auto &it : devs) push_unique (output, it); + return output.size (); + } + }; + class appx_deps: virtual public com_info + { + using Base = com_info ; + public: + using Base::Base; + size_t dependencies (_Out_ std::vector &output) const + { + return EnumerateComInterface (pointer (), output, [] (IAppxManifestPackageDependency *&ptr) -> dep_info { + raii endt ([&ptr] () { + if (ptr) ptr->Release (); + ptr = nullptr; + }); + dep_info dep (ptr); + return dep; + }); + } + size_t size () const + { + size_t cnt = 0; + BOOL hasCurrent = FALSE; + HRESULT hr = pointer ()->GetHasCurrent (&hasCurrent); + while (SUCCEEDED (hr) && hasCurrent) + { + hr = pointer ()->GetHasCurrent (&hasCurrent); + if (SUCCEEDED (hr) && hasCurrent) cnt ++; + hr = pointer ()->MoveNext (&hasCurrent); + } + return cnt; + } + }; + class appx_iditem: virtual public com_info + { + using Base = com_info ; + public: + using Base::Base; + appx_iditem (IAppxBundleManifestPackageInfo *ptr): com_info (nullptr) { set (ptr); } + std::wstring file_name () const { return get (&Interface::GetFileName); } + UINT64 offset () const { return get (&Interface::GetOffset); } + HRESULT get_identity (_Outptr_ IAppxManifestPackageId **output) const { return pointer ()->GetPackageId (output); } + appx_id identity () const + { + IAppxManifestPackageId *ip = nullptr; + HRESULT hr = get_identity (&ip); + return appx_id (ip); + } + APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE type () const { return get (&Interface::GetPackageType); } + HRESULT get_qualified_resources (_Outptr_ IAppxManifestQualifiedResourcesEnumerator **output) const { return pointer ()->GetResources (output); } + appx_qres qualified_resources () const + { + IAppxManifestQualifiedResourcesEnumerator *ip = nullptr; + get_qualified_resources (&ip); + return appx_qres (ip); + } + UINT64 size () const { return get (&Interface::GetSize); } + }; + class appx_iditems: virtual public com_info + { + using Base = com_info ; + public: + using Base::Base; + size_t enumerate (_In_ std::function callback, APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE enumtype = (APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE)-1) const + { + BOOL hasCurrent = FALSE; + HRESULT hr = pointer ()->GetHasCurrent (&hasCurrent); + size_t cnt = 0; + while (SUCCEEDED (hr) && hasCurrent) + { + CComPtr item; + hr = pointer ()->GetCurrent (&item); + if (SUCCEEDED (hr)) + { + APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE type = (APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE)-1; + item->GetPackageType (&type); + switch (type) + { + case APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE::APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE_APPLICATION: + cnt ++; + callback (item); + break; + case APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE::APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE_RESOURCE: + cnt ++; + callback (item); + break; + default: + cnt ++; + callback (item); + break; + } + } + hr = pointer ()->MoveNext (&hasCurrent); + } + return cnt; + } + size_t enumerate (_Out_ std::vector &output, _In_ APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE enumtype = (APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE)-1) const + { + output.clear (); + enumerate ([&output] (IAppxBundleManifestPackageInfo *ip) { + output.push_back (appx_iditem (ip)); + }, enumtype); + return output.size (); + } + size_t enumerate (_Out_ std::vector &apps, _Out_ std::vector &ress) const + { + return enumerate ([&apps, &ress] (IAppxBundleManifestPackageInfo *p) { + APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE type; + p->GetPackageType (&type); + switch (type) + { + case APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE::APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE_APPLICATION: + apps.push_back (appx_iditem (p)); break; + case APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE::APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE_RESOURCE: + ress.push_back (appx_iditem (p)); break; + } + }); + } + size_t application_packages (_Out_ std::vector &output) const { return enumerate (output, APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE::APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE_APPLICATION); } + size_t resource_packages (_Out_ std::vector &output) const { return enumerate (output, APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE::APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE_RESOURCE); } + size_t size () const + { + BOOL hasCurrent = FALSE; + HRESULT hr = pointer ()->GetHasCurrent (&hasCurrent); + size_t cnt = 0; + while (SUCCEEDED (hr) && hasCurrent) + { + cnt ++; + hr = pointer ()->MoveNext (&hasCurrent); + } + return cnt; + } + }; +} +class appxreader: virtual public com_info_quote +{ + using Base = com_info_quote ; + template HRESULT get (IComPtr iptr, Fn func, ReturnType *retvalue) const { if (!iptr) return E_FAIL; return (iptr->*func) (retvalue); } + using Package = IAppxPackageReader; + using Manifest = IAppxManifestReader; + public: + using Base::Base; + HRESULT manifest (_Outptr_ IAppxManifestReader **output) const { return get (pointer (), &Package::GetManifest, output); } + template HRESULT get_from_manifest (Func fn, _Outptr_ IComPtr *output) const + { + CComPtr m; + HRESULT hr = manifest (&m); + if (FAILED (hr)) return hr; + return hr = get (m, 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); + } + appx_info::appx_res resources () const + { + CComPtr m; + HRESULT hr = manifest (&m); + return appx_info::appx_res (m); + } + HRESULT get_properties (_Outptr_ IAppxManifestProperties **output) const { return get_from_manifest (&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 + { + CComPtr m; + HRESULT hr = manifest (&m); + return appx_info::appx_preq (m); + } + HRESULT get_applications (_Outptr_ IAppxManifestApplicationsEnumerator **output) const { return get_from_manifest (&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 (&Manifest::GetCapabilities, output); } + HRESULT get_device_capabilities (_Outptr_ IAppxManifestDeviceCapabilitiesEnumerator **output) const { return get_from_manifest (&Manifest::GetDeviceCapabilities, output); } + appx_info::appx_capabs capabilities () const + { + APPX_CAPABILITIES caps; + IAppxManifestDeviceCapabilitiesEnumerator *ip = nullptr; + get_device_capabilities (&ip); + if (SUCCEEDED (get_capabilities (&caps))) return appx_info::appx_capabs (ip, caps); + return appx_info::appx_capabs (ip); + } + HRESULT get_dependencies (_Outptr_ IAppxManifestPackageDependenciesEnumerator **output) const { return get_from_manifest (&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 apps; + if (app.app_user_model_ids (apps)) return PackageRole::application; + else return PackageRole::unknown; + } + HRESULT payload_stream (_In_ const std::wstring &filename, _Outptr_ IAppxFile **output) const { return pointer ()->GetPayloadFile (filename.c_str (), output); } + HRESULT payloads_stream (_Outptr_ IAppxFilesEnumerator **output) const { return pointer ()->GetPayloadFiles (output); } + HRESULT footprint_stream (_In_ APPX_FOOTPRINT_FILE_TYPE type, _Outptr_ IAppxFile **output) const { return pointer ()->GetFootprintFile (type, output); } + HRESULT resources_pri_stream (_Outptr_ IAppxFile **output) const { return payload_stream (L"resources.pri", output); } + HRESULT blockmap (_Outptr_ IAppxBlockMapReader **output) const { return pointer ()->GetBlockMap (output); } +}; +class bundlereader: virtual public com_info_quote +{ + using Base = com_info_quote ; + public: + using Base::Base; + template HRESULT get (IComPtr iptr, Fn func, ReturnType *retvalue) const { if (!iptr) return E_FAIL; return (iptr->*func) (retvalue); } + using Package = IAppxBundleReader; + using Manifest = IAppxBundleManifestReader; + HRESULT manifest (_Outptr_ IAppxBundleManifestReader **output) const { return get (pointer (), &Package::GetManifest, output); } + template HRESULT get_from_manifest (Func fn, _Outptr_ IComPtr *output) const + { + CComPtr m; + HRESULT hr = manifest (&m); + if (FAILED (hr)) return hr; + return hr = get (m, 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 get_payload_package (_In_ const std::wstring &filename, _Outptr_ IAppxFile **output) const { return pointer ()->GetPayloadPackage (filename.c_str (), output); } + HRESULT get_payload_packages (_Outptr_ IAppxFilesEnumerator **output) const { return pointer ()->GetPayloadPackages (output); } + HRESULT footprint_stream (_In_ APPX_BUNDLE_FOOTPRINT_FILE_TYPE type, _Outptr_ IAppxFile **output) const { return pointer ()->GetFootprintFile (type, output); } + HRESULT blockmap (_Outptr_ IAppxBlockMapReader **output) const { return pointer ()->GetBlockMap (output); } + HRESULT payload_package (_In_ const std::wstring &filename, std::function callback) const + { + CComPtr appxfile; + CComPtr stream; + CComPtr ip; + HRESULT hr = S_OK; + if (FAILED (hr = get_payload_package (filename, &appxfile))) return hr; + if (FAILED (hr = appxfile->GetStream (&stream))) return hr; + hr = GetAppxPackageReader (stream, &ip); + if (callback) callback (ip); + return hr; + } + size_t payload_packages (std::function callback) const + { + CComPtr iae; + BOOL hasCurrent = false; + HRESULT hr = get_payload_packages (&iae); + hr = iae->GetHasCurrent (&hasCurrent); + size_t cnt = 0; + while (SUCCEEDED (hr) && hasCurrent) + { + CComPtr afile; + if (SUCCEEDED (iae->GetCurrent (&afile))) + { + LPWSTR filename = nullptr; + raii endt ([&filename] () { + if (filename) CoTaskMemFree (filename); + filename = nullptr; + }); + afile->GetName (&filename); + CComPtr stream; + if (SUCCEEDED (afile->GetStream (&stream))) + { + CComPtr ip; + if (SUCCEEDED (GetAppxPackageReader (stream, &ip))) + { + cnt ++; + if (callback) callback (ip, filename); + } + } + } + hr = iae->MoveNext (&hasCurrent); + } + return cnt; + } + HRESULT random_application_package (_Outptr_ IAppxPackageReader **output) const + { + CComPtr iditems; + HRESULT hr = get_package_id_items (&iditems); + if (FAILED (hr)) return hr; + BOOL hc = FALSE; + hr = iditems->GetHasCurrent (&hc); + bool find = false; + std::wstring fname = L""; + while (SUCCEEDED (hr) && hc) + { + CComPtr iditem; + hr = iditems->GetCurrent (&iditem); + if (SUCCEEDED (hr)) + { + APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE ptype; + if (!(SUCCEEDED (iditem->GetPackageType (&ptype)) && ptype == APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE::APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE_APPLICATION)) + { + hr = iditems->MoveNext (&hc); + continue; + } + LPWSTR lpfname = nullptr; + raii endt ([&lpfname] () { + if (lpfname) CoTaskMemFree (lpfname); + lpfname = nullptr; + }); + if (SUCCEEDED (iditem->GetFileName (&lpfname)) && lpfname) + { + fname += lpfname; + find = true; + break; + } + } + hr = iditems->MoveNext (&hc); + } + if (!find) return FAILED (hr) ? hr : E_FAIL; + CComPtr afile; + hr = get_payload_package (fname, &afile); + if (FAILED (hr)) return hr; + CComPtr ist; + hr = afile->GetStream (&ist); + if (FAILED (hr)) return hr; + return GetAppxPackageReader (ist, output); + } + HRESULT random_resource_package (_Outptr_ IAppxPackageReader **output) const + { + CComPtr iditems; + HRESULT hr = get_package_id_items (&iditems); + if (FAILED (hr)) return hr; + BOOL hc = FALSE; + hr = iditems->GetHasCurrent (&hc); + bool find = false; + std::wstring fname = L""; + while (SUCCEEDED (hr) && hc) + { + CComPtr iditem; + hr = iditems->GetCurrent (&iditem); + if (SUCCEEDED (hr)) + { + APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE ptype; + if (!(SUCCEEDED (iditem->GetPackageType (&ptype)) && ptype == APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE::APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE_RESOURCE)) + { + hr = iditems->MoveNext (&hc); + continue; + } + LPWSTR lpfname = nullptr; + raii endt ([&lpfname] () { + if (lpfname) CoTaskMemFree (lpfname); + lpfname = nullptr; + }); + if (SUCCEEDED (iditem->GetFileName (&lpfname)) && lpfname) + { + fname += lpfname; + find = true; + break; + } + } + hr = iditems->MoveNext (&hc); + } + if (!find) return FAILED (hr) ? hr : E_FAIL; + CComPtr afile; + hr = get_payload_package (fname, &afile); + if (FAILED (hr)) return hr; + CComPtr ist; + hr = afile->GetStream (&ist); + if (FAILED (hr)) return hr; + return GetAppxPackageReader (ist, output); + } + size_t application_packages (std::function callback) const + { + CComPtr iditems; + HRESULT hr = get_package_id_items (&iditems); + if (FAILED (hr)) return hr; + BOOL hc = FALSE; + hr = iditems->GetHasCurrent (&hc); + std::vector files; + while (SUCCEEDED (hr) && hc) + { + CComPtr iditem; + hr = iditems->GetCurrent (&iditem); + if (SUCCEEDED (hr)) + { + APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE ptype; + if (!(SUCCEEDED (iditem->GetPackageType (&ptype)) && ptype == APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE::APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE_APPLICATION)) + { hr = iditems->MoveNext (&hc); continue; } + LPWSTR lpfname = nullptr; + raii endt ([&lpfname] () { if (lpfname) CoTaskMemFree (lpfname); lpfname = nullptr; }); + if (SUCCEEDED (iditem->GetFileName (&lpfname)) && lpfname) files.push_back (lpfname); + } + hr = iditems->MoveNext (&hc); + } + size_t cnt = 0; + for (auto &fname : files) + { + CComPtr afile; + hr = get_payload_package (fname, &afile); + if (SUCCEEDED (hr)) + { + CComPtr istrm; + hr = afile->GetStream (&istrm); + if (SUCCEEDED (hr)) + { + CComPtr aread; + hr = GetAppxPackageReader (istrm, &aread); + if (SUCCEEDED (hr)) + { + cnt ++; + callback (aread); + } + } + } + } + return cnt; + } + size_t resource_packages (std::function callback) const + { + CComPtr iditems; + HRESULT hr = get_package_id_items (&iditems); + if (FAILED (hr)) return hr; + BOOL hc = FALSE; + hr = iditems->GetHasCurrent (&hc); + std::vector files; + while (SUCCEEDED (hr) && hc) + { + CComPtr iditem; + hr = iditems->GetCurrent (&iditem); + if (SUCCEEDED (hr)) + { + APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE ptype; + if (!(SUCCEEDED (iditem->GetPackageType (&ptype)) && ptype == APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE::APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE_RESOURCE)) + { hr = iditems->MoveNext (&hc); continue; } + LPWSTR lpfname = nullptr; + raii endt ([&lpfname] () { if (lpfname) CoTaskMemFree (lpfname); lpfname = nullptr; }); + if (SUCCEEDED (iditem->GetFileName (&lpfname)) && lpfname) files.push_back (lpfname); + } + hr = iditems->MoveNext (&hc); + } + size_t cnt = 0; + for (auto &fname : files) + { + CComPtr afile; + hr = get_payload_package (fname, &afile); + if (SUCCEEDED (hr)) + { + CComPtr istrm; + hr = afile->GetStream (&istrm); + if (SUCCEEDED (hr)) + { + CComPtr aread; + hr = GetAppxPackageReader (istrm, &aread); + if (SUCCEEDED (hr)) + { + cnt ++; + callback (aread); + } + } + } + } + return cnt; + } +}; + +class package +{ + IAppxPackageReader *appx = nullptr; + IAppxBundleReader *bundle = nullptr; + public: + ~package () { destroy (); } + package (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 = GetBundleReader (filepath.c_str (), &bundle); + if (SUCCEEDED (hr)) return true; + if (bundle) { bundle->Release (); bundle = nullptr; } + hr = GetPackageReader (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; + } + appxreader appx_reader () const { return appxreader (*(IAppxPackageReader **)&this->appx); } + bundlereader bundle_reader () const { return bundlereader (*(IAppxBundleReader **)&this->bundle); } +}; diff --git a/pkgread/resource.h b/pkgread/resource.h new file mode 100644 index 0000000..155cbf3 --- /dev/null +++ b/pkgread/resource.h @@ -0,0 +1,14 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by pkgread.rc + +// ¶һĬֵ +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/pkgread/stdafx.cpp b/pkgread/stdafx.cpp new file mode 100644 index 0000000..8a12f34 --- /dev/null +++ b/pkgread/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : ֻ׼ļԴļ +// pkgread.pch ΪԤͷ +// stdafx.obj ԤϢ + +#include "stdafx.h" + +// TODO: STDAFX.H κĸͷļ +//ڴļ diff --git a/pkgread/stdafx.h b/pkgread/stdafx.h new file mode 100644 index 0000000..b4e958f --- /dev/null +++ b/pkgread/stdafx.h @@ -0,0 +1,26 @@ +// stdafx.h : ׼ϵͳļİļ +// Ǿʹõĵ +// ضĿİļ +// + +#pragma once + +#include "targetver.h" + +#define WIN32_LEAN_AND_MEAN // Windows ͷųʹõ +// Windows ͷļ: +#include + + + +// TODO: ڴ˴óҪͷļ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include \ No newline at end of file diff --git a/pkgread/stringres.h b/pkgread/stringres.h new file mode 100644 index 0000000..6c58348 --- /dev/null +++ b/pkgread/stringres.h @@ -0,0 +1,124 @@ +#pragma once +#include +#include +#include "version.h" +#include "dynarr.h" +#include "norstr.h" +#include "syncutil.h" +static const std::pair captable [] = { + {APPX_CAPABILITY_INTERNET_CLIENT, L"internetClient"}, + {APPX_CAPABILITY_INTERNET_CLIENT_SERVER, L"internetClientServer"}, + {APPX_CAPABILITY_PRIVATE_NETWORK_CLIENT_SERVER, L"privateNetworkClientServer"}, + {APPX_CAPABILITY_DOCUMENTS_LIBRARY, L"documentsLibrary"}, + {APPX_CAPABILITY_PICTURES_LIBRARY, L"picturesLibrary"}, + {APPX_CAPABILITY_VIDEOS_LIBRARY, L"videosLibrary"}, + {APPX_CAPABILITY_MUSIC_LIBRARY, L"musicLibrary"}, + {APPX_CAPABILITY_ENTERPRISE_AUTHENTICATION, L"enterpriseAuthentication"}, + {APPX_CAPABILITY_SHARED_USER_CERTIFICATES, L"sharedUserCertificates"}, + {APPX_CAPABILITY_REMOVABLE_STORAGE, L"removableStorage"}, + {0x00000400, L"appointments"}, // APPX_CAPABILITY_APPOINTMENTS + {0x00000800, L"contacts"}, // APPX_CAPABILITY_CONTACTS + {0x00001000, L"phoneCall"}, + {0x00002000, L"blockedChatMessages"}, + {0x00004000, L"objects3D"}, + {0x00008000, L"allJoyn"}, + {0x00010000, L"codeGeneration"}, + {0x00020000, L"remoteSystem"}, + {0x00040000, L"userAccountInformation"}, + {0x00080000, L"extendedExecution"}, + {0x00100000, L"location"}, + {0x00200000, L"microphone"}, + {0x00400000, L"proximity"}, + {0x00800000, L"webcam"}, + {0x01000000, L"spatialPerception"}, + {0x02000000, L"appointmentsSystem"}, + {0x04000000, L"contactsSystem"}, + {0x08000000, L"phoneCallSystem"}, + {0x10000000, L"smsSend"}, + {0x20000000, L"userDataTasks"}, + {0x40000000, L"userDataTasksSystem"}, + {0x80000000, L"userDataAccounts"} +}; +void CapabilitiesFlagsToNames (APPX_CAPABILITIES caps, std::vector &output) +{ + output.clear (); + output.reserve (16); + UINT64 packageCap = (UINT64)caps; + for (auto &entry : captable) + { + if (packageCap & entry.first) + { + push_unique (output, std::wstring (entry.second)); + } + } +} + +static const std::pair vertable [] = { + {version (10, 0, 25299, 0), L"Windows 11 Version 25H2"}, + {version (10, 0, 24699, 0), L"Windows 11 Version 24H2"}, + {version (10, 0, 24000, 0), L"Windows 11 Version 23H2"}, + {version (10, 0, 22621, 0), L"Windows 11 Version 22H2"}, + {version (10, 0, 22159, 0), L"Windows 11 Initial Release (Version 21H2)"}, + {version (10, 0, 19645, 0), L"Windows 10 Insider Preview (Build 19645)"}, + {version (10, 0, 19541, 0), L"Windows 10 Insider Preview (Build 19541)"}, + {version (10, 0, 19045, 0), L"Windows 10 Version 22H2"}, + {version (10, 0, 19044, 0), L"Windows 10 Version 21H2 (November 2021 Update)"}, + {version (10, 0, 19043, 0), L"Windows 10 Version 21H2 (May 2021 Update)"}, + {version (10, 0, 19042, 0), L"Windows 10 Version 20H2"}, + {version (10, 0, 18362, 0), L"Windows 10 May 2019 Update"}, + {version (10, 0, 17763, 0), L"Windows 10 October 2018 Update"}, + {version (10, 0, 17134, 0), L"Windows 10 April 2018 Update"}, + {version (10, 0, 16299, 0), L"Windows 10 Fall Creators Update"}, + {version (10, 0, 15063, 0), L"Windows 10 Creators Update"}, + {version (10, 0, 14393, 0), L"Windows 10 Anniversary Update"}, + {version (10, 0, 10240, 0), L"Windows 10"}, + {version (10, 0, 0, 0), L"Windows 10"}, + {version (6, 4, 9807, 0), L"Windows 10 Technical Preview"}, + {version (6, 3, 1, 0), L"Windows Phone 8.1"}, + {version (6, 3, 0, 0), L"Windows 8.1"}, + {version (6, 2, 1, 0), L"Windows 8"}, + {version (6, 2, 0, 0), L"Windows 8 Develop Preview"} +}; +std::wstring GetPrerequistOSVersionDescription (const version &ver) +{ + for (const auto &v : vertable) + { + if (ver >= v.first) return std::wstring (v.second); + } + return L"Unknown Windows Version"; +} + +std::vector appitems = +{ + L"Id", + L"DisplayName", + L"BackgroundColor", + L"ForegroundText", + L"ShortName", + L"Square44x44Logo" +}; +std::vector &GetApplicationAttributeItems () { return appitems; } +static CriticalSection g_appcs; +bool PushApplicationAttributeItem (const std::wstring &lpstr) +{ + CreateScopedLock (g_appcs); + size_t len1 = appitems.size (); + push_unique (appitems, lpstr, [] (const std::wstring &v1, const std::wstring &v2) -> bool { + return std::wnstring (v1) == std::wnstring (v2); + }); + return appitems.size () > len1; +} +bool RemoveApplicationAttributeItem (const std::wstring &lpstr) +{ + CreateScopedLock (g_appcs); + auto it = std::find_if (appitems.begin (), appitems.end (), [&] (const std::wstring &v) { + return std::wnstring (v) == std::wnstring (lpstr); + }); + if (it != appitems.end ()) + { + size_t len1 = appitems.size (); + appitems.erase (it); + return appitems.size () < len1; + } + return false; +} \ No newline at end of file diff --git a/pkgread/syncutil.h b/pkgread/syncutil.h new file mode 100644 index 0000000..18ac5d8 --- /dev/null +++ b/pkgread/syncutil.h @@ -0,0 +1,124 @@ +#pragma once +#pragma once +#include +class CriticalSection +{ + private: + CRITICAL_SECTION m_csection; + public: + CriticalSection (DWORD spinCount = 4000) { InitializeCriticalSectionAndSpinCount (&m_csection, spinCount); } + CriticalSection (const CriticalSection &) = delete; + CriticalSection &operator = (const CriticalSection &) = delete; + ~CriticalSection () { DeleteCriticalSection (&m_csection); } + void Lock () { EnterCriticalSection (&m_csection); } + void Unlock () { LeaveCriticalSection (&m_csection); } + bool TryLock () { return TryEnterCriticalSection (&m_csection) != 0; } + class ScopedLock + { + public: + explicit ScopedLock (CriticalSection &cs): m_cs (cs) { m_cs.Lock (); } + ~ScopedLock () { m_cs.Unlock (); } + ScopedLock (const ScopedLock &) = delete; + ScopedLock &operator = (const ScopedLock &) = delete; + private: + CriticalSection& m_cs; + }; +}; + +#define CreateScopedLock(_obj_cs_) CriticalSection::ScopedLock _obj_cs_ (_obj_cs_) + +#ifdef __cplusplus_cli +ref struct TaskStructEvent +{ + typedef array args; + typedef void (*eventfunc) (... args ^args); + eventfunc post; + args ^postargs; + public: + TaskStructEvent ( + eventfunc prefunc, + args ^preargs, + eventfunc postfunc, + args ^postargs + ): post (postfunc), postargs (postargs) + { + if (prefunc == nullptr) { + #pragma message("棺ԤָΪգʼ") + } + if (prefunc) + { + if (preargs) + { + #pragma region ֤ʾ + /* + ʵĿӦӾͼ飬磺 + ValidateArgsType(preargs); + */ + #pragma endregion + prefunc (preargs); + } + else prefunc (gcnew args {}); + } + } + ~TaskStructEvent () + { + if (post == nullptr) + { + #pragma message("棺ָΪգԴ޷ȷͷ") + return; + } + try + { + if (postargs) { post (postargs); } + else { post (gcnew args {}); } + } + catch (Exception ^e) + { + #pragma message("ע⣺е쳣ֶ") + } + } +}; +#define CreateStructEvent(_varname_taskname_, _func_construct_, _args_construct_, _func_destruct_, _args_destruct_) \ +TaskStructEvent _varname_taskname_ ( \ + _func_construct_, \ + _args_construct_, \ + _func_destruct_, \ + _args_destruct_ \ +) +#endif + +#ifdef __cplusplus +#include +#include +template class ScopedEvent +{ + public: + ScopedEvent (PreCallback &&pre, PostCallback &&post) + : m_post (std::forward (post)) + { + static_assert ( + std::is_constructible , PreCallback>::value, + "ԤصתΪ void () " + ); + + if (pre) { pre (); } + } + ~ScopedEvent () noexcept + { + if (m_post) { m_post (); } + } + ScopedEvent (const ScopedEvent &) = delete; + ScopedEvent &operator = (const ScopedEvent &) = delete; + ScopedEvent (ScopedEvent &&) = default; + ScopedEvent &operator =(ScopedEvent &&) = default; + private: + PostCallback m_post; +}; +template auto make_scoped_event (PreFunc &&pre, PostFunc &&post) +{ + return ScopedEvent ( + std::forward (pre), + std::forward (post) + ); +} +#endif \ No newline at end of file diff --git a/pkgread/targetver.h b/pkgread/targetver.h new file mode 100644 index 0000000..416cebf --- /dev/null +++ b/pkgread/targetver.h @@ -0,0 +1,8 @@ +#pragma once + +// SDKDDKVer.h õ߰汾 Windows ƽ̨ + +// ҪΪǰ Windows ƽ̨Ӧó WinSDKVer.h +// _WIN32_WINNT ΪҪֵ֧ƽ̨Ȼٰ SDKDDKVer.h + +#include diff --git a/pkgread/version.h b/pkgread/version.h new file mode 100644 index 0000000..2253e1c --- /dev/null +++ b/pkgread/version.h @@ -0,0 +1,124 @@ +#pragma once +#include +#include +#include +typedef uint64_t UINT64; +typedef int64_t INT64; +typedef uint16_t UINT16; +typedef struct version +{ + UINT16 major = 0, minor = 0, build = 0, revision = 0; + version (UINT64 value): + major ((value >> 0x30) & 0xFFFF), minor ((value >> 0x20) & 0xFFFF), + build ((value >> 0x10) & 0xFFFF), revision ((value) & 0xFFFF) {} + version (UINT16 major, UINT16 minor, UINT16 build, UINT16 revision): + major (major), minor (minor), build (build), revision (revision) {} + version (const std::wstring &verstr) { this->interpret (verstr); } + version (const std::string &verstr) { this->interpret (verstr); } + version () {} + version (const version &other): major (other.major), minor (other.minor), build (other.build), revision (other.revision) {} + version (version &&other) noexcept: major (other.major), minor (other.minor), build (other.build), revision (other.revision) {} + version &operator = (const version &other) + { + if (this != &other) + { + major = other.major; + minor = other.minor; + build = other.build; + revision = other.revision; + } + return *this; + } + version &operator = (version &&other) noexcept + { + if (this != &other) + { + major = other.major; + minor = other.minor; + build = other.build; + revision = other.revision; + } + return *this; + } + version &operator = (UINT64 value) { this->data (value); return *this; } + UINT64 data () const { return (((UINT64)major) << 48) | (((UINT64)minor) << 32) | (((UINT64)build) << 16) | ((UINT64)revision); } + UINT64 data (UINT64 value) + { + major = (value >> 48) & 0xFFFF; + minor = (value >> 32) & 0xFFFF; + build = (value >> 16) & 0xFFFF; + revision = value & 0xFFFF; + return value; + } + std::wstring stringifyw () const + { + std::wstringstream ss; + ss << major << L'.' << minor << L'.' << build << L'.' << revision; + return ss.str (); + } + std::string stringify () const + { + std::stringstream ss; + ss << major << '.' << minor << '.' << build << '.' << revision; + return ss.str (); + } + version &interpret (const std::wstring &verstr) + { + auto result = split (verstr); + if (result.size () > 0) this->major = _wtoi (result [0].c_str ()); + if (result.size () > 1) this->minor = _wtoi (result [1].c_str ()); + if (result.size () > 2) this->build = _wtoi (result [2].c_str ()); + if (result.size () > 3) this->revision = _wtoi (result [3].c_str ()); + return *this; + } + version &interpret (const std::string &verstr) + { + auto result = split (verstr); + if (result.size () > 0) this->major = atoi (result [0].c_str ()); + if (result.size () > 1) this->minor = atoi (result [1].c_str ()); + if (result.size () > 2) this->build = atoi (result [2].c_str ()); + if (result.size () > 3) this->revision = atoi (result [3].c_str ()); + return *this; + } + bool empty () const { return *(UINT64 *)this == 0; } + friend bool operator == (const version &l, const version &r) { return *(UINT64 *)&l == *(UINT64 *)&r; } + friend bool operator == (const version &l, const UINT64 &r) { return l.data () == r; } + friend bool operator == (const UINT64 &r, const version &l) { return l.data () == r; } + friend bool operator < (const version &l, const version &r) { return l.data () < r.data (); } + friend bool operator > (const version &l, const version &r) { return l.data () > r.data (); } + friend bool operator <= (const version &l, const version &r) { return l.data () <= r.data (); } + friend bool operator >= (const version &l, const version &r) { return l.data () >= r.data (); } + friend bool operator != (const version &l, const version &r) { return *(UINT64 *)&l != *(UINT64 *)&r; } + explicit operator bool () const { return !this->empty (); } + bool operator ! () { return this->empty (); } + friend std::ostream &operator << (std::ostream &o, const version &v) { return o << v.major << '.' << v.minor << '.' << v.build << '.' << v.revision; } + friend std::wostream &operator << (std::wostream &o, const version &v) { return o << v.major << '.' << v.minor << '.' << v.build << '.' << v.revision; } + bool equals (const version &r) const { return *this == r; } + INT64 compare (const version &r) const { return this->data () - r.data (); } + static version parse (const std::wstring &value) { return version (value); } + static version parse (const std::string &value) { return version (value); } + static std::wstring stringifyw (const version &v) { return v.stringifyw (); } + static std::string stringify (const version &v) { return v.stringify (); } + static bool equals (const version &l, const version &r) { return l == r; } + static INT64 compare (const version &l, const version &r) { return l.data () - r.data (); } + static version decode (UINT64 value) { return version (value); } + static UINT64 encode (const version &v) { return v.data (); } + protected: + template std::vector split (const StringType &str, typename StringType::value_type delimiter1 = '.', typename StringType::value_type delimiter2 = ',') + { + std::vector result; + std::basic_stringstream ss (str); + StringType segment; + while (std::getline (ss, segment, delimiter1)) + { + size_t pos = 0; + while ((pos = segment.find (delimiter2)) != StringType::npos) + { + result.push_back (segment.substr (0, pos)); + segment.erase (0, pos + 1); + } + if (!segment.empty ()) result.push_back (segment); + } + return result; + } +} Version; \ No newline at end of file diff --git a/prireader/ReadMe.txt b/prireader/ReadMe.txt new file mode 100644 index 0000000..4fe6aba --- /dev/null +++ b/prireader/ReadMe.txt @@ -0,0 +1,30 @@ +======================================================================== + 动态链接库:prireader 项目概述 +======================================================================== + +应用程序向导已为您创建了此 prireader DLL。 + +本文件概要介绍组成 prireader 应用程序的每个文件的内容。 + + +prireader.vcxproj + 这是使用应用程序向导生成的 VC++ 项目的主项目文件,其中包含生成该文件的 Visual C++ 的版本信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。 + +prireader.vcxproj.filters + 这是使用“应用程序向导”生成的 VC++ 项目筛选器文件。它包含有关项目文件与筛选器之间的关联信息。在 IDE 中,通过这种关联,在特定节点下以分组形式显示具有相似扩展名的文件。例如,“.cpp”文件与“源文件”筛选器关联。 + +prireader.cpp + 这是主 DLL 源文件。 + +///////////////////////////////////////////////////////////////////////////// +其他标准文件: + +StdAfx.h, StdAfx.cpp + 这些文件用于生成名为 prireader.pch 的预编译头 (PCH) 文件和名为 StdAfx.obj 的预编译类型文件。 + +///////////////////////////////////////////////////////////////////////////// +其他注释: + +应用程序向导使用“TODO:”注释来指示应添加或自定义的源代码部分。 + +///////////////////////////////////////////////////////////////////////////// diff --git a/prireader/dllmain.cpp b/prireader/dllmain.cpp new file mode 100644 index 0000000..260abc6 --- /dev/null +++ b/prireader/dllmain.cpp @@ -0,0 +1,19 @@ +// dllmain.cpp : DLL Ӧóڵ㡣 +#include "stdafx.h" + +BOOL APIENTRY DllMain( HMODULE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} + diff --git a/prireader/priread.h b/prireader/priread.h new file mode 100644 index 0000000..6f70f09 --- /dev/null +++ b/prireader/priread.h @@ -0,0 +1 @@ +#pragma once diff --git a/prireader/prireader.cpp b/prireader/prireader.cpp new file mode 100644 index 0000000..8fa7053 --- /dev/null +++ b/prireader/prireader.cpp @@ -0,0 +1,22 @@ +// prireader.cpp : DLL Ӧóĵ +// + +#include "stdafx.h" +#include "prireader.h" + + +// ǵһʾ +PRIREADER_API int nprireader=0; + +// ǵһʾ +PRIREADER_API int fnprireader(void) +{ + return 42; +} + +// ѵĹ캯 +// йඨϢ prireader.h +Cprireader::Cprireader() +{ + return; +} diff --git a/prireader/prireader.h b/prireader/prireader.h new file mode 100644 index 0000000..26c097b --- /dev/null +++ b/prireader/prireader.h @@ -0,0 +1,22 @@ +// ifdef Ǵʹ DLL 򵥵 +// ı׼ DLL еļ϶ PRIREADER_EXPORTS +// űġʹô DLL +// κĿϲӦ˷šԴļаļκĿὫ +// PRIREADER_API ΪǴ DLL ģ DLL ô˺궨 +// ΪDZġ +#ifdef PRIREADER_EXPORTS +#define PRIREADER_API __declspec(dllexport) +#else +#define PRIREADER_API __declspec(dllimport) +#endif + +// Ǵ prireader.dll +class PRIREADER_API Cprireader { +public: + Cprireader(void); + // TODO: ڴķ +}; + +extern PRIREADER_API int nprireader; + +PRIREADER_API int fnprireader(void); diff --git a/prireader/prireader.vcxproj b/prireader/prireader.vcxproj new file mode 100644 index 0000000..da5a034 --- /dev/null +++ b/prireader/prireader.vcxproj @@ -0,0 +1,180 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {D8CFAA98-0A77-4C5B-A61B-11EF44206712} + Win32Proj + prireader + 8.1 + + + + DynamicLibrary + true + v140 + Unicode + + + DynamicLibrary + false + v120 + true + Unicode + + + DynamicLibrary + true + v140 + Unicode + + + DynamicLibrary + false + v140 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;PRIREADER_EXPORTS;%(PreprocessorDefinitions) + true + + + Windows + true + + + + + Use + Level3 + Disabled + _DEBUG;_WINDOWS;_USRDLL;PRIREADER_EXPORTS;%(PreprocessorDefinitions) + true + + + Windows + true + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;PRIREADER_EXPORTS;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + + + + + Level3 + Use + MaxSpeed + true + true + NDEBUG;_WINDOWS;_USRDLL;PRIREADER_EXPORTS;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + + + + + + + + + + + + + + + false + + + false + + + false + + + false + + + + + + Create + Create + Create + Create + + + + + + \ No newline at end of file diff --git a/prireader/prireader.vcxproj.filters b/prireader/prireader.vcxproj.filters new file mode 100644 index 0000000..9b749c6 --- /dev/null +++ b/prireader/prireader.vcxproj.filters @@ -0,0 +1,48 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + + + 源文件 + + + 源文件 + + + 源文件 + + + \ No newline at end of file diff --git a/prireader/resource.h b/prireader/resource.h new file mode 100644 index 0000000..31a3d19 --- /dev/null +++ b/prireader/resource.h @@ -0,0 +1,14 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by prireader.rc + +// ¶һĬֵ +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/prireader/stdafx.cpp b/prireader/stdafx.cpp new file mode 100644 index 0000000..4886866 --- /dev/null +++ b/prireader/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : ֻ׼ļԴļ +// prireader.pch ΪԤͷ +// stdafx.obj ԤϢ + +#include "stdafx.h" + +// TODO: STDAFX.H κĸͷļ +//ڴļ \ No newline at end of file diff --git a/prireader/stdafx.h b/prireader/stdafx.h new file mode 100644 index 0000000..db3c4b1 --- /dev/null +++ b/prireader/stdafx.h @@ -0,0 +1,21 @@ +// stdafx.h : ׼ϵͳļİļ +// Ǿʹõĵ +// ضĿİļ +// + +#pragma once + +#include "targetver.h" + +#define WIN32_LEAN_AND_MEAN // Windows ͷųʹõ +// Windows ͷļ: +#include + + +#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // ijЩ CString 캯ʽ + +#include +#include + +// TODO: ڴ˴óҪͷļ +#include diff --git a/prireader/targetver.h b/prireader/targetver.h new file mode 100644 index 0000000..416cebf --- /dev/null +++ b/prireader/targetver.h @@ -0,0 +1,8 @@ +#pragma once + +// SDKDDKVer.h õ߰汾 Windows ƽ̨ + +// ҪΪǰ Windows ƽ̨Ӧó WinSDKVer.h +// _WIN32_WINNT ΪҪֵ֧ƽ̨Ȼٰ SDKDDKVer.h + +#include