diff --git a/AppInstallerReset.sln b/AppInstallerReset.sln
index 586ab1e..e0e0ff3 100644
--- a/AppInstallerReset.sln
+++ b/AppInstallerReset.sln
@@ -4,16 +4,25 @@ Microsoft Visual Studio Solution File, Format Version 12.00
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}"
+ ProjectSection(ProjectDependencies) = postProject
+ {33D91B58-1981-4A3C-B4D1-86EE406CDE12} = {33D91B58-1981-4A3C-B4D1-86EE406CDE12}
+ {A7753282-AA16-43D9-8ACA-7065239DD702} = {A7753282-AA16-43D9-8ACA-7065239DD702}
+ EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pkgread", "pkgread\pkgread.vcxproj", "{A7753282-AA16-43D9-8ACA-7065239DD702}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dlltest", "dlltest\dlltest.vcxproj", "{F5CCB3AB-AC43-432A-862D-4F264760B09B}"
ProjectSection(ProjectDependencies) = postProject
+ {8EAC0230-4990-4E41-8E0F-D641D1561396} = {8EAC0230-4990-4E41-8E0F-D641D1561396}
{33D91B58-1981-4A3C-B4D1-86EE406CDE12} = {33D91B58-1981-4A3C-B4D1-86EE406CDE12}
EndProjectSection
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dlltest", "dlltest\dlltest.vcxproj", "{F5CCB3AB-AC43-432A-862D-4F264760B09B}"
-EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "priformatcli", "..\priformatcli\priformatcli\priformatcli.vcxproj", "{33D91B58-1981-4A3C-B4D1-86EE406CDE12}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pkgmgr", "pkgmgr\pkgmgr.vcxproj", "{8EAC0230-4990-4E41-8E0F-D641D1561396}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "notice", "notice\notice.vcxproj", "{798ED492-EECE-457D-8FD8-129DA93CE126}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@@ -54,6 +63,18 @@ Global
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Release|x64.Build.0 = Release|x64
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Release|x86.ActiveCfg = Release|Win32
{33D91B58-1981-4A3C-B4D1-86EE406CDE12}.Release|x86.Build.0 = Release|Win32
+ {8EAC0230-4990-4E41-8E0F-D641D1561396}.Debug|x64.ActiveCfg = Debug|Win32
+ {8EAC0230-4990-4E41-8E0F-D641D1561396}.Debug|x86.ActiveCfg = Debug|Win32
+ {8EAC0230-4990-4E41-8E0F-D641D1561396}.Debug|x86.Build.0 = Debug|Win32
+ {8EAC0230-4990-4E41-8E0F-D641D1561396}.Release|x64.ActiveCfg = Release|Win32
+ {8EAC0230-4990-4E41-8E0F-D641D1561396}.Release|x86.ActiveCfg = Release|Win32
+ {8EAC0230-4990-4E41-8E0F-D641D1561396}.Release|x86.Build.0 = Release|Win32
+ {798ED492-EECE-457D-8FD8-129DA93CE126}.Debug|x64.ActiveCfg = Debug|Win32
+ {798ED492-EECE-457D-8FD8-129DA93CE126}.Debug|x86.ActiveCfg = Debug|Win32
+ {798ED492-EECE-457D-8FD8-129DA93CE126}.Debug|x86.Build.0 = Debug|Win32
+ {798ED492-EECE-457D-8FD8-129DA93CE126}.Release|x64.ActiveCfg = Release|Win32
+ {798ED492-EECE-457D-8FD8-129DA93CE126}.Release|x86.ActiveCfg = Release|Win32
+ {798ED492-EECE-457D-8FD8-129DA93CE126}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/dlltest/dlltest.vcxproj b/dlltest/dlltest.vcxproj
index 1c8879e..2b864fd 100644
--- a/dlltest/dlltest.vcxproj
+++ b/dlltest/dlltest.vcxproj
@@ -93,6 +93,7 @@
Console
true
+ $(OutDir)pkgread.lib;$(OutDir)priformatcli.lib;$(OutDir)pkgmgr.lib;%(AdditionalDependencies)
@@ -125,7 +126,7 @@
true
true
true
- $(OutDir)pkgread.lib;%(AdditionalDependencies)
+ $(OutDir)pkgread.lib;$(OutDir)priformatcli.lib;%(AdditionalDependencies)
diff --git a/dlltest/main.cpp b/dlltest/main.cpp
index 379361b..18a83bd 100644
--- a/dlltest/main.cpp
+++ b/dlltest/main.cpp
@@ -1,13 +1,18 @@
#include
-#include "..\pkgread\pkgread.h"
#include
#include
#include
#include
+#include
+#include "..\priformatcli\priformatcli.h"
+#include "..\pkgread\pkgread.h"
+#include "..\pkgmgr\pkgmgr.h"
void read_package (const std::wstring &filepath)
{
package_reader pr (filepath);
+ pr.enable_pri_convert (true);
+ pr.use_pri (true);
std::wcout << L"Is Valid: " << (pr.valid () ? L"true" : L"false") << std::endl;
std::wcout << L"Package Type: ";
switch (pr.package_type ())
@@ -61,6 +66,7 @@ void read_package (const std::wstring &filepath)
std::wcout << L"\tDescription: " << prop.description () << std::endl;
std::wcout << L"\tPublisher Display Name: " << prop.publisher_display_name () << std::endl;
std::wcout << L"\tLogo: " << prop.logo () << std::endl;
+ std::wcout << L"\tLogo Base64: " << prop.logo_base64 () << std::endl;
std::wcout << L"\tFramework: " << (prop.framework () ? L"true" : L"false") << std::endl;
std::wcout << L"\tResource Package: " << (prop.resource_package () ? L"true" : L"false") << std::endl;
auto preq = pr.get_prerequisites ();
@@ -134,7 +140,9 @@ void read_package (const std::wstring &filepath)
std::wcout << L"\tApplication" << cnt ++ << std::endl;
for (auto &it_s : it)
{
- std::wcout << L"\t\t" << it_s.first << L": " << it_s.second << std::endl;
+ std::wcout << L"\t\t" << it_s.first << L": " << it.newat (it_s.first) << std::endl;
+ std::wstring base64 = it.newat_base64 (it_s.first);
+ if (!base64.empty ()) std::wcout << L"\t\t" << it_s.first << L" (Base64): " << base64 << std::endl;
}
}
}
@@ -154,20 +162,57 @@ void read_package (const std::wstring &filepath)
}
}
}
-
+using cbfunc = std::function ;
+void ProgressCallback (DWORD dwProgress, void *pCustom)
+{
+ if (auto func = reinterpret_cast (pCustom)) (*func)(dwProgress);
+}
+HRESULT AddAppxPackage (const std::wstring path, cbfunc callback, std::wstring &errorcode, std::wstring &detailmsg)
+{
+ LPWSTR ec = nullptr, dm = nullptr;
+ struct reltask
+ {
+ using endfunc = std::function ;
+ endfunc endtask = nullptr;
+ reltask (endfunc et): endtask (et) {}
+ ~reltask () { if (endtask) endtask (); }
+ } relt ([=] () {
+ if (ec) free (ec);
+ if (dm) free (dm);
+ });
+ HRESULT hr = AddAppxPackageFromPath (path.c_str (), nullptr, DEPOLYOPTION_NONE, ProgressCallback, &callback, &ec, &dm);
+ errorcode.clear ();
+ detailmsg.clear ();
+ if (ec) errorcode = ec;
+ if (dm) detailmsg = dm;
+ return hr;
+}
int main (int argc, char *argv [])
{
setlocale (LC_ALL, "");
std::wcout.imbue (std::locale ("", LC_CTYPE));
std::wcout << L"Please enter the file path: " << std::endl;
std::wcout << L"\\> ";
- std::wstring pkgPathStr = L"E:\\Profiles\\Bruce\\Desktop\\resources.pri";
- //std::getline (std::wcin, pkgPathStr);
+ std::wstring pkgPathStr = L"E:\\Profiles\\Bruce\\Desktop\\Discourse.appx";
+ pkgPathStr = L"F:\\BaiduNetdiskDownload\\Collection4\\Microsoft.BingFinance_2015.709.2014.2069_neutral_~_8wekyb3d8bbwe\\FinanceApp_3.0.4.336_x86.appx";
+ pkgPathStr = L"F:\\BaiduNetdiskDownload\\Collection4\\Microsoft.BingFinance_2015.709.2014.2069_neutral_~_8wekyb3d8bbwe.appxbundle";
+ pkgPathStr = L"";
+ if (pkgPathStr.empty ()) std::getline (std::wcin, pkgPathStr);
pkgPathStr.erase (
std::remove (pkgPathStr.begin (), pkgPathStr.end (), L'\"'),
pkgPathStr.end ()
);
-
+ std::wcout << L"Installing ..." << std::endl;
+ std::wstring ec, dm;
+ HRESULT hr = AddAppxPackage (pkgPathStr, [] (int progress) {
+ std::wcout << L"\r " << progress << L"%";
+ }, ec, dm);
+ if (SUCCEEDED (hr)) std::wcout << std::endl << L"Installed Successfully." << std::endl;
+ else
+ {
+ std::wcout << std::endl << L"Exception: " << ec << L"(0x" << std::hex << std::setw (8) << std::setfill (L'0') << hr << L")" << std::endl;
+ std::wcout << L"Detail Message: " << dm << std::endl;
+ }
system ("pause");
return 0;
}
\ No newline at end of file
diff --git a/notice/ReadMe.txt b/notice/ReadMe.txt
new file mode 100644
index 0000000..6fbb505
--- /dev/null
+++ b/notice/ReadMe.txt
@@ -0,0 +1,30 @@
+========================================================================
+ 动态链接库:pkgmgr 项目概述
+========================================================================
+
+应用程序向导已为您创建了此 pkgmgr DLL。
+
+本文件概要介绍组成 pkgmgr 应用程序的每个文件的内容。
+
+
+pkgmgr.vcxproj
+ 这是使用应用程序向导生成的 VC++ 项目的主项目文件,其中包含生成该文件的 Visual C++ 的版本信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。
+
+pkgmgr.vcxproj.filters
+ 这是使用“应用程序向导”生成的 VC++ 项目筛选器文件。它包含有关项目文件与筛选器之间的关联信息。在 IDE 中,通过这种关联,在特定节点下以分组形式显示具有相似扩展名的文件。例如,“.cpp”文件与“源文件”筛选器关联。
+
+pkgmgr.cpp
+ 这是主 DLL 源文件。
+
+/////////////////////////////////////////////////////////////////////////////
+其他标准文件:
+
+StdAfx.h, StdAfx.cpp
+ 这些文件用于生成名为 pkgmgr.pch 的预编译头 (PCH) 文件和名为 StdAfx.obj 的预编译类型文件。
+
+/////////////////////////////////////////////////////////////////////////////
+其他注释:
+
+应用程序向导使用“TODO:”注释来指示应添加或自定义的源代码部分。
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/notice/dllmain.cpp b/notice/dllmain.cpp
new file mode 100644
index 0000000..260abc6
--- /dev/null
+++ b/notice/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/notice/notice.cpp b/notice/notice.cpp
new file mode 100644
index 0000000..fb4413b
--- /dev/null
+++ b/notice/notice.cpp
@@ -0,0 +1,39 @@
+// pkgmgr.cpp : DLL Ӧóĵ
+//
+
+#include "stdafx.h"
+#include "notice.h"
+#include "raii.h"
+#include "version.h"
+
+#undef GetFullPathName
+std::wstring GetFullPathName (const std::wstring &lpFileName)
+{
+ if (lpFileName.empty ()) return L"";
+ DWORD length = GetFullPathNameW (lpFileName.c_str (), 0, nullptr, nullptr);
+ if (length == 0) return L"";
+ std::vector buffer (length + 1, L'\0');
+ DWORD result = GetFullPathNameW (lpFileName.c_str (), length, buffer.data (), nullptr);
+ if (result == 0) return L"";
+ return std::wstring (buffer.data (), result);
+}
+
+std::wstring g_swExceptionCode = L"";
+std::wstring g_swExceptionDetail = L"";
+
+struct destruct
+{
+ std::function endtask = nullptr;
+ destruct (std::function pfunc): endtask (pfunc) {}
+ ~destruct () { if (endtask) endtask (); }
+};
+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;
+}
+
diff --git a/notice/notice.h b/notice/notice.h
new file mode 100644
index 0000000..ca66229
--- /dev/null
+++ b/notice/notice.h
@@ -0,0 +1,39 @@
+// ifdef Ǵʹ DLL
+// ı DLL еļ϶ PKGMGR_EXPORTS
+// űġʹô DLL
+// κĿϲӦ˷šԴļаļκĿὫ
+// PKGMGR_API ΪǴ DLL ģ DLL ô˺궨
+// ΪDZġ
+#ifdef NOTICE_EXPORTS
+#define NOTICE_API __declspec(dllexport)
+#else
+#define NOTICE_API __declspec(dllimport)
+#endif
+
+// API áAppxںУ˾Ϊ˷ֹƵĺ
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+#ifdef __cplusplus
+#define _DEFAULT_INIT_VALUE_(_init_value_) = _init_value_
+#ifndef PKGMGR_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
+
+#ifdef _DEFAULT_INIT_VALUE_
+#undef _DEFAULT_INIT_VALUE_
+#endif
+#ifdef _DEFAULT_INIT_VALUE_FORFUNC_
+#undef _DEFAULT_INIT_VALUE_FORFUNC_
+#endif
+#ifdef __cplusplus
+}
+#endif
diff --git a/notice/notice.vcxproj b/notice/notice.vcxproj
new file mode 100644
index 0000000..c46e2d1
--- /dev/null
+++ b/notice/notice.vcxproj
@@ -0,0 +1,107 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+
+ {798ED492-EECE-457D-8FD8-129DA93CE126}
+ Win32Proj
+ notice
+ notice
+
+
+
+ DynamicLibrary
+ true
+ Unicode
+ v120
+ false
+
+
+ DynamicLibrary
+ false
+ Unicode
+ v120
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(VCINSTALLDIR)\vcpackages;$(VCInstallDir)atlmfc\lib;$(VCInstallDir)lib;$(WindowsSdkDir)\References\CommonConfiguration\Neutral;$(ReferencePath)
+
+
+ $(VCINSTALLDIR)\vcpackages;$(VCInstallDir)atlmfc\lib;$(VCInstallDir)lib;$(WindowsSdkDir)\References\CommonConfiguration\Neutral;$(ReferencePath)
+
+
+
+
+ NotUsing
+ Level3
+ Disabled
+ /ZW:nostdlib /FUplatform.winmd /FUwindows.winmd %(AdditionalOptions)
+ WIN32;_DEBUG;_WINDOWS;_USRDLL;NOTICE_EXPORTS;%(PreprocessorDefinitions)
+ true
+ false
+
+
+ Windows
+ true
+ RequireAdministrator
+
+
+
+
+ NotUsing
+ Level3
+ MaxSpeed
+ true
+ true
+ /ZW:nostdlib /FUplatform.winmd /FUWindows.winmd %(AdditionalOptions)
+ WIN32;NDEBUG;_WINDOWS;_USRDLL;NOTICE_EXPORTS;%(PreprocessorDefinitions)
+ true
+
+
+ Windows
+ true
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。
+
+
+
+
\ No newline at end of file
diff --git a/notice/notice.vcxproj.filters b/notice/notice.vcxproj.filters
new file mode 100644
index 0000000..0ea694c
--- /dev/null
+++ b/notice/notice.vcxproj.filters
@@ -0,0 +1,45 @@
+
+
+
+
+ {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/notice/packages.config b/notice/packages.config
new file mode 100644
index 0000000..c2da1c1
--- /dev/null
+++ b/notice/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/notice/raii.h b/notice/raii.h
new file mode 100644
index 0000000..cc82c4f
--- /dev/null
+++ b/notice/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/notice/stdafx.cpp b/notice/stdafx.cpp
new file mode 100644
index 0000000..1945e44
--- /dev/null
+++ b/notice/stdafx.cpp
@@ -0,0 +1,8 @@
+// stdafx.cpp : ֻļԴļ
+// pkgmgr.pch ΪԤͷ
+// stdafx.obj ԤϢ
+
+#include "stdafx.h"
+
+// TODO: STDAFX.H κĸͷļ
+//ڴļ
diff --git a/notice/stdafx.h b/notice/stdafx.h
new file mode 100644
index 0000000..0a55300
--- /dev/null
+++ b/notice/stdafx.h
@@ -0,0 +1,38 @@
+// 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
+#include
+#include
+#include
+#include
+
+using namespace Microsoft::WRL;
+using namespace ABI::Windows::UI::Notifications;
+using namespace ABI::Windows::Data::Xml::Dom;
+using namespace Microsoft::WRL::Wrappers;
+
+#include
+#include
\ No newline at end of file
diff --git a/notice/targetver.h b/notice/targetver.h
new file mode 100644
index 0000000..416cebf
--- /dev/null
+++ b/notice/targetver.h
@@ -0,0 +1,8 @@
+#pragma once
+
+// SDKDDKVer.h õ߰汾 Windows ƽ̨
+
+// ҪΪǰ Windows ƽ̨Ӧó WinSDKVer.h
+// _WIN32_WINNT ΪҪֵ֧ƽ̨Ȼٰ SDKDDKVer.h
+
+#include
diff --git a/notice/version.h b/notice/version.h
new file mode 100644
index 0000000..5091c21
--- /dev/null
+++ b/notice/version.h
@@ -0,0 +1,125 @@
+#pragma once
+#include
+#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): 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)
+ {
+ 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/pkgmgr/ReadMe.txt b/pkgmgr/ReadMe.txt
new file mode 100644
index 0000000..6fbb505
--- /dev/null
+++ b/pkgmgr/ReadMe.txt
@@ -0,0 +1,30 @@
+========================================================================
+ 动态链接库:pkgmgr 项目概述
+========================================================================
+
+应用程序向导已为您创建了此 pkgmgr DLL。
+
+本文件概要介绍组成 pkgmgr 应用程序的每个文件的内容。
+
+
+pkgmgr.vcxproj
+ 这是使用应用程序向导生成的 VC++ 项目的主项目文件,其中包含生成该文件的 Visual C++ 的版本信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。
+
+pkgmgr.vcxproj.filters
+ 这是使用“应用程序向导”生成的 VC++ 项目筛选器文件。它包含有关项目文件与筛选器之间的关联信息。在 IDE 中,通过这种关联,在特定节点下以分组形式显示具有相似扩展名的文件。例如,“.cpp”文件与“源文件”筛选器关联。
+
+pkgmgr.cpp
+ 这是主 DLL 源文件。
+
+/////////////////////////////////////////////////////////////////////////////
+其他标准文件:
+
+StdAfx.h, StdAfx.cpp
+ 这些文件用于生成名为 pkgmgr.pch 的预编译头 (PCH) 文件和名为 StdAfx.obj 的预编译类型文件。
+
+/////////////////////////////////////////////////////////////////////////////
+其他注释:
+
+应用程序向导使用“TODO:”注释来指示应添加或自定义的源代码部分。
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/pkgmgr/dllmain.cpp b/pkgmgr/dllmain.cpp
new file mode 100644
index 0000000..260abc6
--- /dev/null
+++ b/pkgmgr/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/pkgmgr/pkgmgr.cpp b/pkgmgr/pkgmgr.cpp
new file mode 100644
index 0000000..2e5f9e6
--- /dev/null
+++ b/pkgmgr/pkgmgr.cpp
@@ -0,0 +1,629 @@
+// pkgmgr.cpp : DLL Ӧóĵ
+//
+
+#include "stdafx.h"
+#include "pkgmgr.h"
+#include "raii.h"
+#include "version.h"
+
+#undef GetFullPathName
+std::wstring GetFullPathName (const std::wstring &lpFileName)
+{
+ if (lpFileName.empty ()) return L"";
+ DWORD length = GetFullPathNameW (lpFileName.c_str (), 0, nullptr, nullptr);
+ if (length == 0) return L"";
+ std::vector buffer (length + 1, L'\0');
+ DWORD result = GetFullPathNameW (lpFileName.c_str (), length, buffer.data (), nullptr);
+ if (result == 0) return L"";
+ return std::wstring (buffer.data (), result);
+}
+
+std::wstring g_swExceptionCode = L"";
+std::wstring g_swExceptionDetail = L"";
+
+struct destruct
+{
+ std::function endtask = nullptr;
+ destruct (std::function pfunc): endtask (pfunc) {}
+ ~destruct () { if (endtask) endtask (); }
+};
+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;
+}
+using onprogress = AsyncOperationProgressHandler ;
+using onprogresscomp = AsyncOperationWithProgressCompletedHandler ;
+using progressopt = IAsyncOperationWithProgress ^;
+template HRESULT RunPackageManagerOperation (TAsyncOpCreator asyncCreator, PKGMRR_PROGRESSCALLBACK pfCallback, void *pCustom, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
+{
+ g_swExceptionCode = L"";
+ g_swExceptionDetail = L"";
+ if (pErrorCode) *pErrorCode = nullptr;
+ if (pDetailMsg) *pDetailMsg = nullptr;
+ try
+ {
+ HANDLE hCompEvt = nullptr;
+ destruct closeevt ([&hCompEvt] () {
+ if (hCompEvt) { CloseHandle (hCompEvt); hCompEvt = nullptr; }
+ });
+ hCompEvt = CreateEventExW (nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS);
+ if (!hCompEvt) return E_FAIL;
+ auto depopt = asyncCreator ();
+ depopt->Progress = ref new onprogress ([pfCallback, pCustom] (progressopt operation, DeploymentProgress progress) {
+ if (pfCallback) pfCallback ((DWORD)progress.percentage, pCustom);
+ });
+ depopt->Completed = ref new onprogresscomp ([&hCompEvt] (progressopt, AsyncStatus) {
+ SetEvent (hCompEvt);
+ });
+ WaitForSingleObject (hCompEvt, INFINITE);
+ switch (depopt->Status)
+ {
+ case AsyncStatus::Completed:
+ return S_OK;
+ case AsyncStatus::Error:
+ {
+ auto depresult = depopt->GetResults ();
+ auto errorcode = depopt->ErrorCode;
+ HResult hr = errorcode;
+ String ^errstr = Exception::CreateException (errorcode.Value)->ToString ();
+ g_swExceptionCode += errstr && errstr->Data () ? errstr->Data () : L"";
+ g_swExceptionDetail += depresult->ErrorText->Data ();
+ if (pErrorCode) *pErrorCode = _wcsdup (g_swExceptionCode.c_str ());
+ if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
+ return (HRESULT)errorcode.Value;
+ }
+ case AsyncStatus::Canceled:
+ g_swExceptionDetail = L"Installation Canceled";
+ if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
+ return E_ABORT;
+ case AsyncStatus::Started:
+ g_swExceptionDetail = L"Installation is Running";
+ if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
+ return E_PENDING;
+ }
+ }
+ catch (Exception ^e)
+ {
+ g_swExceptionDetail = e->ToString ()->Data ();
+ if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
+ return (SUCCEEDED ((HRESULT)e->HResult) ? E_FAIL : (HRESULT)e->HResult);
+ }
+ catch (const std::exception &e)
+ {
+ g_swExceptionDetail = StringToWString (e.what () ? e.what () : "Unknown exception.");
+ if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
+ return E_FAIL;
+ }
+ catch (...)
+ {
+ g_swExceptionDetail = L"Unknown exception";
+ if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
+ return E_FAIL;
+ }
+ return E_FAIL;
+}
+[MTAThread]
+HRESULT AddAppxPackageFromURI (LPCWSTR lpPkgFileUri, PCREGISTER_PACKAGE_DEFENDENCIES alpDepUrlList, DWORD dwDeployOption, PKGMRR_PROGRESSCALLBACK pfCallback, void *pCustom, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
+{
+ return RunPackageManagerOperation ([=] () {
+ auto pkgmgr = ref new PackageManager ();
+ auto depuris = ref new Platform::Collections::Vector ();
+ if (alpDepUrlList)
+ {
+ for (size_t i = 0; i < alpDepUrlList->dwSize; i ++)
+ {
+ auto &pstr = alpDepUrlList->alpDepUris [i];
+ try
+ {
+ if (pstr && *pstr)
+ {
+ auto depuristr = ref new String (pstr);
+ Uri ^duri = nullptr;
+ try { duri = ref new Uri (depuristr); }
+ catch (Exception ^e)
+ {
+ try
+ {
+ std::wstring fullpath = GetFullPathName (pstr ? pstr : L"");
+ if (fullpath.empty ()) fullpath = pstr ? pstr : L"";
+ duri = ref new Uri (ref new String (fullpath.c_str ()));
+ }
+ catch (Exception ^e) { continue; }
+ }
+ depuris->Append (duri);
+ }
+ }
+ catch (Exception ^e) { continue; }
+ }
+ }
+ if (depuris->Size > 0) depuris = nullptr;
+ auto ope = pkgmgr->AddPackageAsync (ref new Uri (ref new String (lpPkgFileUri)), depuris, (DeploymentOptions)dwDeployOption);
+ return ope;
+ }, pfCallback, pCustom, pErrorCode, pDetailMsg);
+}
+[MTAThread]
+HRESULT AddAppxPackageFromPath (LPCWSTR lpPkgPath, PCREGISTER_PACKAGE_DEFENDENCIES alpDepUrlList, DWORD dwDeployOption, PKGMRR_PROGRESSCALLBACK pfCallback, void *pCustom, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
+{
+ std::wstring fullpath = GetFullPathName (lpPkgPath ? lpPkgPath : L"");
+ if (fullpath.empty ()) fullpath = lpPkgPath ? lpPkgPath : L"";
+ return AddAppxPackageFromURI (fullpath.c_str (), alpDepUrlList, dwDeployOption, pfCallback, pCustom, pErrorCode, pDetailMsg);
+}
+std::wstring WinRTStringToStdString (String ^pstr)
+{
+ try { if (!pstr) return L""; return (pstr->Data () ? pstr->Data () : L""); }
+ catch (...) {} return L"";
+}
+#define PlatformGetStringValue(mpObj, _prop_) \
+ ([&] () -> std::wstring { \
+ auto strptr = (mpObj)->_prop_; \
+ return WinRTStringToStdString (strptr); \
+ }) ()
+void SidToAccountName (const std::wstring &sidString, std::wstring &stringSid)
+{
+ PSID sid = nullptr;
+ raii lrel ([&sid] () {
+ if (sid) LocalFree (sid);
+ sid = nullptr;
+ });
+ if (ConvertStringSidToSidW (sidString.c_str (), &sid))
+ {
+ DWORD nameCharCount = 0;
+ DWORD domainNameCharCount = 0;
+ SID_NAME_USE sidType;
+ LookupAccountSidW (nullptr, sid, nullptr, &nameCharCount, nullptr, &domainNameCharCount, &sidType);
+ std::vector namebuf (nameCharCount + 1);
+ std::vector domainNameBuf (domainNameCharCount + 1);
+ ZeroMemory (namebuf.data (), (nameCharCount + 1) * sizeof (WCHAR));
+ ZeroMemory (domainNameBuf.data (), (domainNameCharCount + 1) * sizeof (WCHAR));
+ if (LookupAccountSidW (nullptr, sid, namebuf.data (), &nameCharCount, domainNameBuf.data (), &domainNameCharCount, &sidType))
+ {
+ stringSid = domainNameBuf.data ();
+ stringSid += stringSid + L"\\" + namebuf.data ();
+ }
+ }
+ if (stringSid.length () == 0) stringSid = sidString;
+}
+struct pkg_info
+{
+ struct identity
+ {
+ std::wstring name = L"";
+ std::wstring publisher = L"";
+ std::wstring fullname = L"";
+ std::wstring familyname = L"";
+ std::wstring resourceid = L"";
+ std::wstring publisherid = L"";
+ uint16_t architecture = -1;
+ Version version;
+ } id;
+ struct properities
+ {
+ std::wstring displayname = L"";
+ std::wstring description = L"";
+ std::wstring publisher = L"";
+ std::wstring logo = L"";
+ bool framework = false;
+ bool resource_package = false;
+ } prop;
+ bool bundle = false;
+ bool development_mode = false;
+ std::wstring installlocation = L"";
+ std::wstring users = L"";
+ std::wstring sids = L"";
+ std::vector dependencies;
+ static pkg_info parse (Windows::ApplicationModel::Package ^pkg, Windows::Management::Deployment::PackageManager ^mgr)
+ {
+ pkg_info pi;
+ if (!pkg) throw ref new InvalidArgumentException ("No package found.");
+ #define WAPParseSetValue(_left_part_, _right_part_, _default_value_) \
+ do { try { _left_part_ = _right_part_; } catch (...) { _left_part_ = _default_value_; } } while (false)
+ #define WAPParseSetStringValue(_left_part_, _right_part_) \
+ WAPParseSetValue (_left_part_, WinRTStringToStdString (_right_part_), L"")
+ WAPParseSetStringValue (pi.id.name, pkg->Id->Name);
+ WAPParseSetStringValue (pi.id.publisher, pkg->Id->Publisher);
+ WAPParseSetStringValue (pi.id.fullname, pkg->Id->FullName);
+ WAPParseSetStringValue (pi.id.familyname, pkg->Id->FamilyName);
+ WAPParseSetStringValue (pi.id.publisherid, pkg->Id->PublisherId);
+ WAPParseSetStringValue (pi.id.resourceid, pkg->Id->ResourceId);
+ try { pi.id.version = version (pkg->Id->Version.Major, pkg->Id->Version.Minor, pkg->Id->Version.Build, pkg->Id->Version.Revision); } catch (...) {}
+ WAPParseSetValue (pi.id.architecture, (WORD)pkg->Id->Architecture, (WORD)-1);
+ WAPParseSetStringValue (pi.prop.displayname, pkg->DisplayName);
+ WAPParseSetStringValue (pi.prop.description, pkg->Description);
+ WAPParseSetStringValue (pi.prop.publisher, pkg->PublisherDisplayName);
+ WAPParseSetStringValue (pi.prop.logo, pkg->Logo->ToString ());
+ WAPParseSetValue (pi.prop.framework, pkg->IsFramework, false);
+ WAPParseSetValue (pi.prop.resource_package, pkg->IsResourcePackage, false);
+ WAPParseSetValue (pi.bundle, pkg->IsBundle, false);
+ WAPParseSetValue (pi.development_mode, pkg->IsDevelopmentMode, false);
+ WAPParseSetStringValue (pi.installlocation, pkg->InstalledLocation->Path);
+ try
+ {
+ size_t i = 0;
+ auto users = mgr->FindUsers (pkg->Id->FullName);
+ for (auto it : users)
+ {
+ {
+ std::wstring sid = L"";
+ SidToAccountName (it->UserSecurityId->Data (), sid);
+ if (i) pi.users += L';';
+ pi.users += sid;
+ }
+ {
+ std::wstring sid;
+ WAPParseSetStringValue (sid, it->UserSecurityId);
+ if (i) pi.sids += L';';
+ pi.users += sid;
+ }
+ i ++;
+ }
+ }
+ catch (...) {}
+ try
+ {
+ auto deps = pkg->Dependencies;
+ for (auto it : deps)
+ {
+ auto deppkg = pkg_info::parse (it, mgr);
+ deppkg.dependencies.clear ();
+ pi.dependencies.push_back (deppkg);
+ }
+ }
+ catch (...) {}
+ return pi;
+ #ifdef WAPParseSetStringValue
+ #undef WAPParseSetStringValue
+ #endif
+ #ifdef WAPParseSetValue
+ #undef WAPParseSetValue
+ #endif
+ }
+ // صķǻΪԽṹҪ̬롣ܳ
+ void to_c_struct (std::vector &bytesret) const
+ {
+ bytesret.clear ();
+ bytesret.resize (sizeof (FIND_PACKAGE_INFO) * (this->dependencies.size () + 1));
+ FIND_PACKAGE_INFO &fpi = *(FIND_PACKAGE_INFO *)bytesret.data ();
+ fpi.piIdentity.lpFamilyName = this->id.familyname.c_str ();
+ fpi.piIdentity.lpFullName = this->id.fullname.c_str ();
+ fpi.piIdentity.lpName = this->id.name.c_str ();
+ fpi.piIdentity.lpPublisher = this->id.publisher.c_str ();
+ fpi.piIdentity.lpPublisherId = this->id.publisherid.c_str ();
+ fpi.piIdentity.lpResourceId = this->id.resourceid.c_str ();
+ fpi.piIdentity.qwVersion = this->id.version.data ();
+ fpi.piIdentity.wProcessArchitecture = this->id.architecture;
+ fpi.piProperties.bIsBundle = this->bundle;
+ fpi.piProperties.bIsDevelopmentMode = this->development_mode;
+ fpi.piProperties.bIsFramework = this->prop.framework;
+ fpi.piProperties.bIsResourcePackage = this->prop.resource_package;
+ fpi.piProperties.lpDescription = this->prop.description.c_str ();
+ fpi.piProperties.lpDisplayName = this->prop.displayname.c_str ();
+ fpi.piProperties.lpLogoUri = this->prop.logo.c_str ();
+ fpi.piProperties.lpPublisher = this->prop.publisher.c_str ();
+ fpi.dwDependencesSize = this->dependencies.size ();
+ fpi.lpInstallLocation = this->installlocation.c_str ();
+ fpi.lpUsers = this->users.c_str ();
+ FIND_PACKAGE_INFO *deps = (FIND_PACKAGE_INFO *)&fpi.ullBuffer;
+ for (size_t i = 0; i < this->dependencies.size (); i ++)
+ {
+ std::vector depbytes;
+ this->dependencies [i].to_c_struct (depbytes);
+ deps [i] = *(FIND_PACKAGE_INFO *)depbytes.data ();
+ }
+ }
+};
+[STAThread]
+HRESULT FindAppxPackageByCallback (std::function pfCallback, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
+{
+ g_swExceptionCode = L"";
+ g_swExceptionDetail = L"";
+ try
+ {
+ auto pkgmgr = ref new PackageManager ();
+ auto pkgarr = pkgmgr->FindPackages ();
+ for (auto pkg : pkgarr)
+ {
+ auto pkginfo = pkg_info::parse (pkg, pkgmgr);
+ if (pfCallback) pfCallback (pkginfo);
+ }
+ return S_OK;
+ }
+ catch (AccessDeniedException ^e)
+ {
+ g_swExceptionDetail = e->ToString ()->Data ();
+ if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
+ return (SUCCEEDED ((HRESULT)e->HResult) ? E_FAIL : (HRESULT)e->HResult);
+ }
+ catch (Exception ^e)
+ {
+ g_swExceptionDetail = e->ToString ()->Data ();
+ if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
+ return (SUCCEEDED ((HRESULT)e->HResult) ? E_FAIL : (HRESULT)e->HResult);
+ }
+ catch (const std::exception &e)
+ {
+ g_swExceptionDetail = StringToWString (e.what () ? e.what () : "Unknown exception.");
+ if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
+ return E_FAIL;
+ }
+ catch (...)
+ {
+ g_swExceptionDetail = L"Unknown exception";
+ if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
+ return E_FAIL;
+ }
+ return E_FAIL;
+}
+[STAThread]
+HRESULT GetAppxPackages (PKGMGR_FINDENUMCALLBACK pfCallback, void *pCustom, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
+{
+ return FindAppxPackageByCallback ([&pCustom, &pfCallback] (pkg_info &pi) {
+ std::vector bytes;
+ pi.to_c_struct (bytes);
+ if (pfCallback) pfCallback ((FIND_PACKAGE_INFO *)bytes.data (), pCustom);
+ }, pErrorCode, pDetailMsg);
+}
+[MTAThread]
+HRESULT RemoveAppxPackage (LPCWSTR lpPkgFullName, PKGMRR_PROGRESSCALLBACK pfCallback, void *pCustom, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
+{
+ return RunPackageManagerOperation ([=] () {
+ auto pkgmgr = ref new PackageManager ();
+ return pkgmgr->RemovePackageAsync (ref new String (lpPkgFullName));
+ }, pfCallback, pCustom, pErrorCode, pDetailMsg);
+}
+[MTAThread]
+HRESULT CleanupAppxPackage (LPCWSTR lpPkgName, LPCWSTR lpUserSID, PKGMRR_PROGRESSCALLBACK pfCallback, void *pCustom, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
+{
+ return RunPackageManagerOperation ([=] () {
+ auto pkgmgr = ref new PackageManager ();
+ return pkgmgr->CleanupPackageForUserAsync (ref new String (lpPkgName), ref new String (lpUserSID));
+ }, pfCallback, pCustom, pErrorCode, pDetailMsg);
+}
+[MTAThread]
+HRESULT RegisterAppxPackageByUri (LPCWSTR lpManifestUri, PCREGISTER_PACKAGE_DEFENDENCIES alpDependencyUriList, DWORD dwDeployOption, PKGMRR_PROGRESSCALLBACK pfCallback, void *pCustom, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
+{
+ return RunPackageManagerOperation ([=] () {
+ auto pkgmgr = ref new PackageManager ();
+ auto depuris = ref new Platform::Collections::Vector ();
+ if (alpDependencyUriList)
+ {
+ for (size_t i = 0; i < alpDependencyUriList->dwSize; i ++)
+ {
+ auto &pstr = alpDependencyUriList->alpDepUris [i];
+ try
+ {
+ if (pstr && *pstr)
+ {
+ auto depuristr = ref new String (pstr);
+ Uri ^duri = nullptr;
+ try { duri = ref new Uri (depuristr); }
+ catch (Exception ^e)
+ {
+ try
+ {
+ std::wstring fullpath = GetFullPathName (pstr ? pstr : L"");
+ if (fullpath.empty ()) fullpath = pstr ? pstr : L"";
+ duri = ref new Uri (ref new String (fullpath.c_str ()));
+ }
+ catch (Exception ^e) { continue; }
+ }
+ depuris->Append (duri);
+ }
+ }
+ catch (Exception ^e) { continue; }
+ }
+ }
+ if (depuris->Size > 0) depuris = nullptr;
+ return pkgmgr->RegisterPackageAsync (ref new Uri (ref new String (lpManifestUri)), depuris, (DeploymentOptions)dwDeployOption);
+ }, pfCallback, pCustom, pErrorCode, pDetailMsg);
+}
+[MTAThread]
+HRESULT RegisterAppxPackageByPath (LPCWSTR lpManifestPath, PCREGISTER_PACKAGE_DEFENDENCIES alpDependencyUriList, DWORD dwDeployOption, PKGMRR_PROGRESSCALLBACK pfCallback, void *pCustom, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
+{
+ std::wstring fullpath = GetFullPathName (lpManifestPath ? lpManifestPath : L"");
+ if (fullpath.empty ()) fullpath = lpManifestPath ? lpManifestPath : L"";
+ return RegisterAppxPackageByPath (fullpath.c_str (), alpDependencyUriList, dwDeployOption, pfCallback, pCustom, pErrorCode, pDetailMsg);
+}
+[MTAThread]
+HRESULT RegisterAppxPackageByFullName (LPCWSTR lpPackageFullName, PCREGISTER_PACKAGE_DEFENDENCIES alpDepFullNameList, DWORD dwDeployOption, PKGMRR_PROGRESSCALLBACK pfCallback, void *pCustom, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
+{
+ return RunPackageManagerOperation ([=] () {
+ auto pkgmgr = ref new PackageManager ();
+ auto depuris = ref new Platform::Collections::Vector ();
+ if (alpDepFullNameList)
+ {
+ for (size_t i = 0; i < alpDepFullNameList->dwSize; i ++)
+ {
+ auto &pstr = alpDepFullNameList->alpDepUris [i];
+ try { if (pstr && *pstr) depuris->Append (ref new String (pstr)); }
+ catch (Exception ^e) { continue; }
+ }
+ }
+ if (depuris->Size > 0) depuris = nullptr;
+ return pkgmgr->RegisterPackageByFullNameAsync (ref new String (lpPackageFullName), depuris, (DeploymentOptions)dwDeployOption);
+ }, pfCallback, pCustom, pErrorCode, pDetailMsg);
+}
+template HRESULT ExecPackageManagerFunctionNoReturn (TFunction func, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
+{
+ g_swExceptionCode = L"";
+ g_swExceptionDetail = L"";
+ try
+ {
+ func ();
+ return S_OK;
+ }
+ catch (Exception ^e)
+ {
+ g_swExceptionDetail = e->ToString ()->Data ();
+ if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
+ return (SUCCEEDED ((HRESULT)e->HResult) ? E_FAIL : (HRESULT)e->HResult);
+ }
+ catch (const std::exception &e)
+ {
+ g_swExceptionDetail = StringToWString (e.what () ? e.what () : "Unknown exception.");
+ if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
+ return E_FAIL;
+ }
+ catch (...)
+ {
+ g_swExceptionDetail = L"Unknown exception";
+ if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
+ return E_FAIL;
+ }
+ return E_FAIL;
+}
+[STAThread]
+HRESULT SetAppxPackageStatus (LPCWSTR lpPackageFullName, DWORD dwStatus, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
+{
+ return ExecPackageManagerFunctionNoReturn ([=] () {
+ auto pkgmgr = ref new PackageManager ();
+ pkgmgr->SetPackageState (ref new String (lpPackageFullName), (Windows::Management::Deployment::PackageState)dwStatus);
+ }, pErrorCode, pDetailMsg);
+}
+[MTAThread]
+HRESULT StageAppxPackageFromURI (LPCWSTR lpFileUri, PCREGISTER_PACKAGE_DEFENDENCIES alpDepUriList, DWORD dwDeployOption, PKGMRR_PROGRESSCALLBACK pfCallback, void *pCustom, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
+{
+ return RunPackageManagerOperation ([=] () {
+ auto pkgmgr = ref new PackageManager ();
+ auto depuris = ref new Platform::Collections::Vector ();
+ if (alpDepUriList)
+ {
+ for (size_t i = 0; i < alpDepUriList->dwSize; i ++)
+ {
+ auto &pstr = alpDepUriList->alpDepUris [i];
+ try
+ {
+ if (pstr && *pstr)
+ {
+ auto depuristr = ref new String (pstr);
+ Uri ^duri = nullptr;
+ try { duri = ref new Uri (depuristr); }
+ catch (Exception ^e)
+ {
+ try
+ {
+ std::wstring fullpath = GetFullPathName (pstr ? pstr : L"");
+ if (fullpath.empty ()) fullpath = pstr ? pstr : L"";
+ duri = ref new Uri (ref new String (fullpath.c_str ()));
+ }
+ catch (Exception ^e) { continue; }
+ }
+ depuris->Append (duri);
+ }
+ }
+ catch (Exception ^e) { continue; }
+ }
+ }
+ if (depuris->Size > 0) depuris = nullptr;
+ return pkgmgr->StagePackageAsync (ref new Uri (ref new String (lpFileUri)), depuris, (DeploymentOptions)dwDeployOption);
+ }, pfCallback, pCustom, pErrorCode, pDetailMsg);
+}
+[MTAThread]
+HRESULT StageAppxPackageFromPath (LPCWSTR lpPkgPath, PCREGISTER_PACKAGE_DEFENDENCIES alpDepUriList, DWORD dwDeployOption, PKGMRR_PROGRESSCALLBACK pfCallback, void *pCustom, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
+{
+ std::wstring fullpath = GetFullPathName (lpPkgPath ? lpPkgPath : L"");
+ if (fullpath.empty ()) fullpath = lpPkgPath ? lpPkgPath : L"";
+ return StageAppxPackageFromPath (fullpath.c_str (), alpDepUriList, dwDeployOption, pfCallback, pCustom, pErrorCode, pDetailMsg);
+}
+[MTAThread]
+HRESULT StageAppxUserData (LPCWSTR lpPackageFullName, PKGMRR_PROGRESSCALLBACK pfCallback, void *pCustom, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
+{
+ return RunPackageManagerOperation ([=] () {
+ auto pkgmgr = ref new PackageManager ();
+ return pkgmgr->StageUserDataAsync (ref new String (lpPackageFullName));
+ }, pfCallback, pCustom, pErrorCode, pDetailMsg);
+}
+[MTAThread]
+HRESULT UpdateAppxPackageFromURI (LPCWSTR lpPkgFileUri, PCREGISTER_PACKAGE_DEFENDENCIES alpDepUrlList, DWORD dwDeployOption, PKGMRR_PROGRESSCALLBACK pfCallback, void *pCustom, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
+{
+ return RunPackageManagerOperation ([=] () {
+ auto pkgmgr = ref new PackageManager ();
+ auto depuris = ref new Platform::Collections::Vector ();
+ if (alpDepUrlList)
+ {
+ for (size_t i = 0; i < alpDepUrlList->dwSize; i ++)
+ {
+ auto &pstr = alpDepUrlList->alpDepUris [i];
+ try
+ {
+ if (pstr && *pstr)
+ {
+ auto depuristr = ref new String (pstr);
+ Uri ^duri = nullptr;
+ try { duri = ref new Uri (depuristr); }
+ catch (Exception ^e)
+ {
+ try
+ {
+ std::wstring fullpath = GetFullPathName (pstr ? pstr : L"");
+ if (fullpath.empty ()) fullpath = pstr ? pstr : L"";
+ duri = ref new Uri (ref new String (fullpath.c_str ()));
+ }
+ catch (Exception ^e) { continue; }
+ }
+ depuris->Append (duri);
+ }
+ }
+ catch (Exception ^e) { continue; }
+ }
+ }
+ if (depuris->Size > 0) depuris = nullptr;
+ return pkgmgr->UpdatePackageAsync (ref new Uri (ref new String (lpPkgFileUri)), depuris, (DeploymentOptions)dwDeployOption);
+ }, pfCallback, pCustom, pErrorCode, pDetailMsg);
+}
+[MTAThread]
+HRESULT UpdateAppxPackageFromPath (LPCWSTR lpPkgPath, PCREGISTER_PACKAGE_DEFENDENCIES alpDepUrlList, DWORD dwDeployOption, PKGMRR_PROGRESSCALLBACK pfCallback, void *pCustom, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
+{
+ std::wstring fullpath = GetFullPathName (lpPkgPath ? lpPkgPath : L"");
+ if (fullpath.empty ()) fullpath = lpPkgPath ? lpPkgPath : L"";
+ return UpdateAppxPackageFromURI (fullpath.c_str (), alpDepUrlList, dwDeployOption, pfCallback, pCustom, pErrorCode, pDetailMsg);
+}
+[STAThread]
+HRESULT FindAppxPackage (LPCWSTR lpPackageFullName, PKGMGR_FINDENUMCALLBACK pfCallback, void *pCustom, LPWSTR *pErrorCode, LPWSTR *pDetailMsg)
+{
+ g_swExceptionCode = L"";
+ g_swExceptionDetail = L"";
+ try
+ {
+ auto pkgmgr = ref new PackageManager ();
+ auto pkg = pkgmgr->FindPackage (ref new String (lpPackageFullName));
+ auto pkginfo = pkg_info::parse (pkg, pkgmgr);
+ std::vector bytes;
+ pkginfo.to_c_struct (bytes);
+ if (pfCallback) pfCallback ((FIND_PACKAGE_INFO *)bytes.data (), pCustom);
+ return S_OK;
+ }
+ catch (AccessDeniedException ^e)
+ {
+ g_swExceptionDetail = e->ToString ()->Data ();
+ if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
+ return (SUCCEEDED ((HRESULT)e->HResult) ? E_FAIL : (HRESULT)e->HResult);
+ }
+ catch (Exception ^e)
+ {
+ g_swExceptionDetail = e->ToString ()->Data ();
+ if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
+ return (SUCCEEDED ((HRESULT)e->HResult) ? E_FAIL : (HRESULT)e->HResult);
+ }
+ catch (const std::exception &e)
+ {
+ g_swExceptionDetail = StringToWString (e.what () ? e.what () : "Unknown exception.");
+ if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
+ return E_FAIL;
+ }
+ catch (...)
+ {
+ g_swExceptionDetail = L"Unknown exception";
+ if (pDetailMsg) *pDetailMsg = _wcsdup (g_swExceptionDetail.c_str ());
+ return E_FAIL;
+ }
+ return E_FAIL;
+}
+[STAThread]
+LPCWSTR GetPackageManagerLastErrorCode () { return g_swExceptionCode.c_str (); }
+[STAThread]
+LPCWSTR GetPackageManagerLastErrorDetailMessage () { return g_swExceptionDetail.c_str (); }
\ No newline at end of file
diff --git a/pkgmgr/pkgmgr.h b/pkgmgr/pkgmgr.h
new file mode 100644
index 0000000..551f86d
--- /dev/null
+++ b/pkgmgr/pkgmgr.h
@@ -0,0 +1,192 @@
+// ifdef Ǵʹ DLL
+// ı DLL еļ϶ PKGMGR_EXPORTS
+// űġʹô DLL
+// κĿϲӦ˷šԴļаļκĿὫ
+// PKGMGR_API ΪǴ DLL ģ DLL ô˺궨
+// ΪDZġ
+#ifdef PKGMGR_EXPORTS
+#define PKGMGR_API __declspec(dllexport)
+#else
+#define PKGMGR_API __declspec(dllimport)
+#endif
+
+// API áAppxںУ˾Ϊ˷ֹƵĺ
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+#ifdef __cplusplus
+#define _DEFAULT_INIT_VALUE_(_init_value_) = _init_value_
+#ifndef PKGMGR_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
+
+ // ȻصpCustom ԴԶ
+ typedef void (*PKGMRR_PROGRESSCALLBACK) (DWORD dwProgress, void *pCustom);
+
+#define PKGMGR_RESULT_OK S_OK
+#define PKGMGR_RESULT_ERROR E_FAIL
+#define PKGMGR_RESULT_CANCEL E_ABORT
+#define PKGMGR_RESULT_STARTED E_PENDING
+
+ typedef struct _REGISTER_PACKAGE_DEFENDENCIES
+ {
+ DWORD dwSize _DEFAULT_INIT_VALUE_ (0);
+ LPWSTR alpDepUris [1];
+ } REGISTER_PACKAGE_DEFENDENCIES, *PREGISTER_PACKAGE_DEFENDENCIES;
+ typedef const REGISTER_PACKAGE_DEFENDENCIES CREGISTER_PACKAGE_DEFENDENCIES, *PCREGISTER_PACKAGE_DEFENDENCIES;
+
+ // ֵ Windows::Management::Deployment::DeploymentOptions һһӦҪд API
+ // ֻˡ
+ // ɲĵ https://learn.microsoft.com/zh-cn/uwp/api/windows.management.deployment.deploymentoptions?view=winrt-26100
+
+ // ôѡʱӦýڿģʽ°װ йؿģʽϢ ע
+ // ʹôѡùؼӦÿܽѡʹá
+ // ѡһʹãýERROR_INSTALL_FAILED
+#define DEPOLYOPTION_FORCE_APP_SHUTDOWN 0x00000001
+ // ǰʹô˰ڴ˰κΰǿƹرðḶ̌ԱԼעᡣ
+#define DEPOLYOPTION_DEVELOPMENT_MODE 0x00000002
+ // ôѡʱָʾӦԴԼ顣 Чݴעûݸ Դ
+ // ǿƶааԡ ûעаԴ
+ // Windows
+#define DEPOLYOPTION_INSTALL_ALL_RESOURCES 0x00000020
+ // ʹĬΪ
+#define DEPOLYOPTION_NONE 0x00000000
+ // װһ Appx/AppxBundle/Msix/MsixBundle
+ // ע⣺ļ·Ϊ DOS/NT 磺C:\Windows\...
+ // ú PowerShell Add-AppxPackage
+ // dwDeployOption DEPOLYOPTION_*
+ // ĴϢ free ͷ
+ PKGMGR_API HRESULT AddAppxPackageFromPath (LPCWSTR lpPkgPath, PCREGISTER_PACKAGE_DEFENDENCIES alpDepUrlList _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), DWORD dwDeployOption _DEFAULT_INIT_VALUE_FORFUNC_ (DEPOLYOPTION_NONE), PKGMRR_PROGRESSCALLBACK pfCallback _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), void *pCustom _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pErrorCode _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pDetailMsg _DEFAULT_INIT_VALUE_FORFUNC_ (NULL));
+ // װһ Appx/AppxBundle/Msix/MsixBundle
+ // ע⣺ļ·Ϊ URI
+ // ú PowerShell Add-AppxPackage
+ // dwDeployOption DEPOLYOPTION_*
+ // ĴϢ free ͷ
+ PKGMGR_API HRESULT AddAppxPackageFromURI (LPCWSTR lpFileUri, PCREGISTER_PACKAGE_DEFENDENCIES alpDepFullNameList _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), DWORD dwDeployOption _DEFAULT_INIT_VALUE_FORFUNC_ (DEPOLYOPTION_NONE), PKGMRR_PROGRESSCALLBACK pfCallback _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), void *pCustom _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pErrorCode _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pDetailMsg _DEFAULT_INIT_VALUE_FORFUNC_ (NULL));
+
+ typedef struct _FIND_PACKAGE_ID
+ {
+ UINT64 qwVersion _DEFAULT_INIT_VALUE_ (0);
+ // x86: 0
+ // x64: 9
+ // Arm: 5
+ // Neutral: 11
+ // Arm64: 12
+ // Unknown: 65535(-1)
+ WORD wProcessArchitecture _DEFAULT_INIT_VALUE_ ((WORD)-1);
+ WORD wPadding [3];
+ LPCWSTR lpName _DEFAULT_INIT_VALUE_ (NULL);
+ LPCWSTR lpFullName _DEFAULT_INIT_VALUE_ (NULL);
+ LPCWSTR lpFamilyName _DEFAULT_INIT_VALUE_ (NULL);
+ LPCWSTR lpPublisher _DEFAULT_INIT_VALUE_ (NULL);
+ LPCWSTR lpPublisherId _DEFAULT_INIT_VALUE_ (NULL);
+ LPCWSTR lpResourceId _DEFAULT_INIT_VALUE_ (NULL);
+ } FIND_PACKAGE_ID, *PFIND_PACKAGE_ID;
+ typedef struct _FIND_PACKAGE_PROPERTIES
+ {
+ LPCWSTR lpDisplayName _DEFAULT_INIT_VALUE_ (NULL);
+ LPCWSTR lpDescription _DEFAULT_INIT_VALUE_ (NULL);
+ LPCWSTR lpPublisher _DEFAULT_INIT_VALUE_ (NULL);
+ LPCWSTR lpLogoUri _DEFAULT_INIT_VALUE_ (NULL);
+ BOOL bIsFramework _DEFAULT_INIT_VALUE_ (FALSE);
+ BOOL bIsResourcePackage _DEFAULT_INIT_VALUE_ (FALSE);
+ BOOL bIsBundle _DEFAULT_INIT_VALUE_ (FALSE);
+ BOOL bIsDevelopmentMode _DEFAULT_INIT_VALUE_ (FALSE);
+ } FIND_PACKAGE_PROPERTIES, *PFIND_PACKAGE_PROPERTIES;
+ typedef struct _FIND_PACKAGE_INFO
+ {
+ FIND_PACKAGE_ID piIdentity;
+ FIND_PACKAGE_PROPERTIES piProperties;
+ LPCWSTR lpInstallLocation _DEFAULT_INIT_VALUE_ (NULL);
+ // û ";" ָ
+ LPCWSTR lpUsers _DEFAULT_INIT_VALUE_ (NULL);
+ // û ";" ָ
+ LPCWSTR lpSIDs _DEFAULT_INIT_VALUE_ (NULL);
+ DWORD dwDependencesSize _DEFAULT_INIT_VALUE_ (0);
+ // 壬ڴ
+ DWORD dwPadding _DEFAULT_INIT_VALUE_ (0);
+ // 壬̬֮ͨڴ淽ʽд顣
+ UINT64 ullBuffer _DEFAULT_INIT_VALUE_ (0);
+ } FIND_PACKAGE_INFO, *PFIND_PACKAGE_INFO;
+ typedef const FIND_PACKAGE_INFO CFIND_PACKAGE_INFO, *LPCFIND_PACKAGE_INFO;
+ // עصʱָ벻Ҫֶͷ
+ typedef void (*PKGMGR_FINDENUMCALLBACK) (LPCFIND_PACKAGE_INFO pNowItem, void *pCustom);
+ // ͨصȡаϢصԶݡصֵжǷɹ
+ // ú PowerShell Get-AppxPackage
+ // ע⣺صаϢģҲͷšźִԶͷšҪڻصпһݡ
+ // ĴϢ free ͷ
+ PKGMGR_API HRESULT GetAppxPackages (PKGMGR_FINDENUMCALLBACK pfCallback, void *pCustom _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pErrorCode _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pDetailMsg _DEFAULT_INIT_VALUE_FORFUNC_ (NULL));
+ // ƳһѾװϵӦáע⣺ǰ
+ // ĴϢ free ͷ
+ PKGMGR_API HRESULT RemoveAppxPackage (LPCWSTR lpPkgFullName, PKGMRR_PROGRESSCALLBACK pfCallback _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), void *pCustom _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pErrorCode _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pDetailMsg _DEFAULT_INIT_VALUE_FORFUNC_ (NULL));
+ // ָûָ ɾûûļΪûװİ
+ // ĴϢ free ͷ
+ PKGMGR_API HRESULT CleanupAppxPackage (LPCWSTR lpPkgName, LPCWSTR lpUserSID, PKGMRR_PROGRESSCALLBACK pfCallback _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), void *pCustom _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pErrorCode _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pDetailMsg _DEFAULT_INIT_VALUE_FORFUNC_ (NULL));
+
+ // עӦð
+ // dwDeployOption DEPOLYOPTION_*
+ PKGMGR_API HRESULT RegisterAppxPackageByPath (LPCWSTR lpManifestPath, PCREGISTER_PACKAGE_DEFENDENCIES alpDependencyUriList _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), DWORD dwDeployOption _DEFAULT_INIT_VALUE_FORFUNC_ (DEPOLYOPTION_NONE), PKGMRR_PROGRESSCALLBACK pfCallback _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), void *pCustom _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pErrorCode _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pDetailMsg _DEFAULT_INIT_VALUE_FORFUNC_ (NULL));
+ // עӦð
+ // dwDeployOption DEPOLYOPTION_*
+ PKGMGR_API HRESULT RegisterAppxPackageByUri (LPCWSTR lpManifestUri, PCREGISTER_PACKAGE_DEFENDENCIES alpDependencyUriList _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), DWORD dwDeployOption _DEFAULT_INIT_VALUE_FORFUNC_ (DEPOLYOPTION_NONE), PKGMRR_PROGRESSCALLBACK pfCallback _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), void *pCustom _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pErrorCode _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pDetailMsg _DEFAULT_INIT_VALUE_FORFUNC_ (NULL));
+ // עӦð
+ // dwDeployOption DEPOLYOPTION_*
+ PKGMGR_API HRESULT RegisterAppxPackageByFullName (LPCWSTR lpPackageFullName, PCREGISTER_PACKAGE_DEFENDENCIES alpDepFullNameList _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), DWORD dwDeployOption _DEFAULT_INIT_VALUE_FORFUNC_ (DEPOLYOPTION_NONE), PKGMRR_PROGRESSCALLBACK pfCallback _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), void *pCustom _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pErrorCode _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pDetailMsg _DEFAULT_INIT_VALUE_FORFUNC_ (NULL));
+
+ // https://learn.microsoft.com/zh-cn/uwp/api/windows.management.deployment.packagestate?view=winrt-26100
+
+ // á
+#define PACKAGESTATUS_NORMAL 0
+ // ֤Ч
+#define PACKAGESTATUS_LICENSE_INVALID 1
+ // Чδ֪Դġ
+#define PACKAGESTATUS_MODIFIED 2
+ // Чر۸ġ
+#define PACKAGESTATUS_TAMPERED 3
+ // 磬 ״̬ΪáѴ۸ġȡ
+ // dwStatus ʹ PACKAGESTATUS_*
+ PKGMGR_API HRESULT SetAppxPackageStatus (LPCWSTR lpPackageFullName, DWORD dwStatus, LPWSTR *pErrorCode _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pDetailMsg _DEFAULT_INIT_VALUE_FORFUNC_ (NULL));
+ // ڲע½ ݴ浽ϵͳ
+ // dwDeployOption DEPOLYOPTION_*
+ PKGMGR_API HRESULT StageAppxPackageFromURI (LPCWSTR lpFileUri, PCREGISTER_PACKAGE_DEFENDENCIES alpDepUriList _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), DWORD dwDeployOption _DEFAULT_INIT_VALUE_FORFUNC_ (DEPOLYOPTION_NONE), PKGMRR_PROGRESSCALLBACK pfCallback _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), void *pCustom _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pErrorCode _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pDetailMsg _DEFAULT_INIT_VALUE_FORFUNC_ (NULL));
+ // ڲע½ ݴ浽ϵͳ
+ // dwDeployOption DEPOLYOPTION_*
+ PKGMGR_API HRESULT StageAppxPackageFromPath (LPCWSTR lpFileUri, PCREGISTER_PACKAGE_DEFENDENCIES alpDepUriList _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), DWORD dwDeployOption _DEFAULT_INIT_VALUE_FORFUNC_ (DEPOLYOPTION_NONE), PKGMRR_PROGRESSCALLBACK pfCallback _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), void *pCustom _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pErrorCode _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pDetailMsg _DEFAULT_INIT_VALUE_FORFUNC_ (NULL));
+ // ڲע½ ݴ浽ϵͳ ݴ֮Ϊضûע֮ǰô˷
+ // dwDeployOption DEPOLYOPTION_*
+ PKGMGR_API HRESULT StageAppxUserData (LPCWSTR lpPackageFullName, PKGMRR_PROGRESSCALLBACK pfCallback _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), void *pCustom _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pErrorCode _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pDetailMsg _DEFAULT_INIT_VALUE_FORFUNC_ (NULL));
+ // Ϊǰû㱨Ѱװİ
+ // °İ汾Ѱװİ汾ʱܸѰװİ ǰ汾İʧܡ
+ // ע⣺ļ·Ϊ DOS/NT 磺C:\Windows\...
+ // dwDeployOption DEPOLYOPTION_*
+ // ĴϢ free ͷ
+ PKGMGR_API HRESULT UpdateAppxPackageFromPath (LPCWSTR lpPkgPath, PCREGISTER_PACKAGE_DEFENDENCIES alpDepUrlList _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), DWORD dwDeployOption _DEFAULT_INIT_VALUE_FORFUNC_ (DEPOLYOPTION_NONE), PKGMRR_PROGRESSCALLBACK pfCallback _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), void *pCustom _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pErrorCode _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pDetailMsg _DEFAULT_INIT_VALUE_FORFUNC_ (NULL));
+ // Ϊǰû㱨Ѱװİ
+ // °İ汾Ѱװİ汾ʱܸѰװİ ǰ汾İʧܡ
+ // ע⣺ļ·Ϊ URI
+ // dwDeployOption DEPOLYOPTION_*
+ // ĴϢ free ͷ
+ PKGMGR_API HRESULT UpdateAppxPackageFromURI (LPCWSTR lpFileUri, PCREGISTER_PACKAGE_DEFENDENCIES alpDepFullNameList _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), DWORD dwDeployOption _DEFAULT_INIT_VALUE_FORFUNC_ (DEPOLYOPTION_NONE), PKGMRR_PROGRESSCALLBACK pfCallback _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), void *pCustom _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pErrorCode _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pDetailMsg _DEFAULT_INIT_VALUE_FORFUNC_ (NULL));
+ // йΪκûװָ Ϣ
+ PKGMGR_API HRESULT FindAppxPackage (LPCWSTR lpPackageFullName, PKGMGR_FINDENUMCALLBACK pfCallback, void *pCustom _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pErrorCode _DEFAULT_INIT_VALUE_FORFUNC_ (NULL), LPWSTR *pDetailMsg _DEFAULT_INIT_VALUE_FORFUNC_ (NULL));
+ // ȡ롣벻һУҸЧϢԴϸϢ
+ PKGMGR_API LPCWSTR GetPackageManagerLastErrorCode ();
+ // ȡϸϢdzõ
+ PKGMGR_API LPCWSTR GetPackageManagerLastErrorDetailMessage ();
+#ifdef _DEFAULT_INIT_VALUE_
+#undef _DEFAULT_INIT_VALUE_
+#endif
+#ifdef _DEFAULT_INIT_VALUE_FORFUNC_
+#undef _DEFAULT_INIT_VALUE_FORFUNC_
+#endif
+#ifdef __cplusplus
+}
+#endif
diff --git a/pkgmgr/pkgmgr.vcxproj b/pkgmgr/pkgmgr.vcxproj
new file mode 100644
index 0000000..a291e39
--- /dev/null
+++ b/pkgmgr/pkgmgr.vcxproj
@@ -0,0 +1,96 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+
+ {8EAC0230-4990-4E41-8E0F-D641D1561396}
+ Win32Proj
+ pkgmgr
+ pkgmgr
+
+
+
+ DynamicLibrary
+ true
+ Unicode
+ v120
+ false
+
+
+ DynamicLibrary
+ false
+ Unicode
+ v120
+ false
+
+
+
+
+
+
+
+
+
+
+
+ $(VCINSTALLDIR)\vcpackages;$(VCInstallDir)atlmfc\lib;$(VCInstallDir)lib;$(WindowsSdkDir)\References\CommonConfiguration\Neutral;$(ReferencePath)
+
+
+ $(VCINSTALLDIR)\vcpackages;$(VCInstallDir)atlmfc\lib;$(VCInstallDir)lib;$(WindowsSdkDir)\References\CommonConfiguration\Neutral;$(ReferencePath)
+
+
+
+
+ NotUsing
+ Level3
+ Disabled
+ /ZW:nostdlib /FUplatform.winmd /FUwindows.winmd %(AdditionalOptions)
+ WIN32;_DEBUG;_WINDOWS;_USRDLL;PKGMGR_EXPORTS;%(PreprocessorDefinitions)
+ true
+ false
+
+
+ Windows
+ true
+ RequireAdministrator
+
+
+
+
+ NotUsing
+ Level3
+ MaxSpeed
+ true
+ true
+ /ZW:nostdlib /FUplatform.winmd /FUWindows.winmd %(AdditionalOptions)
+ WIN32;NDEBUG;_WINDOWS;_USRDLL;PKGMGR_EXPORTS;%(PreprocessorDefinitions)
+ true
+
+
+ Windows
+ true
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pkgmgr/pkgmgr.vcxproj.filters b/pkgmgr/pkgmgr.vcxproj.filters
new file mode 100644
index 0000000..b2849fa
--- /dev/null
+++ b/pkgmgr/pkgmgr.vcxproj.filters
@@ -0,0 +1,42 @@
+
+
+
+
+ {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/pkgmgr/raii.h b/pkgmgr/raii.h
new file mode 100644
index 0000000..cc82c4f
--- /dev/null
+++ b/pkgmgr/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/pkgmgr/stdafx.cpp b/pkgmgr/stdafx.cpp
new file mode 100644
index 0000000..1945e44
--- /dev/null
+++ b/pkgmgr/stdafx.cpp
@@ -0,0 +1,8 @@
+// stdafx.cpp : ֻļԴļ
+// pkgmgr.pch ΪԤͷ
+// stdafx.obj ԤϢ
+
+#include "stdafx.h"
+
+// TODO: STDAFX.H κĸͷļ
+//ڴļ
diff --git a/pkgmgr/stdafx.h b/pkgmgr/stdafx.h
new file mode 100644
index 0000000..b363c26
--- /dev/null
+++ b/pkgmgr/stdafx.h
@@ -0,0 +1,30 @@
+// stdafx.h : ϵͳļİļ
+// Ǿʹõĵ
+// ضĿİļ
+//
+
+#pragma once
+
+#include "targetver.h"
+
+#define WIN32_LEAN_AND_MEAN // Windows ͷųʹõ
+// Windows ͷļ:
+#include
+
+
+
+// TODO: ڴ˴óҪͷļ
+#using
+using namespace Platform;
+using namespace Windows::Foundation;
+using namespace Windows::Management::Deployment;
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
\ No newline at end of file
diff --git a/pkgmgr/targetver.h b/pkgmgr/targetver.h
new file mode 100644
index 0000000..416cebf
--- /dev/null
+++ b/pkgmgr/targetver.h
@@ -0,0 +1,8 @@
+#pragma once
+
+// SDKDDKVer.h õ߰汾 Windows ƽ̨
+
+// ҪΪǰ Windows ƽ̨Ӧó WinSDKVer.h
+// _WIN32_WINNT ΪҪֵ֧ƽ̨Ȼٰ SDKDDKVer.h
+
+#include
diff --git a/pkgmgr/version.h b/pkgmgr/version.h
new file mode 100644
index 0000000..5091c21
--- /dev/null
+++ b/pkgmgr/version.h
@@ -0,0 +1,125 @@
+#pragma once
+#include
+#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): 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)
+ {
+ 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/pkgread/localeex.h b/pkgread/localeex.h
index b528d56..b1d5237 100644
--- a/pkgread/localeex.h
+++ b/pkgread/localeex.h
@@ -92,14 +92,23 @@ void GetLocaleElaboratedCodeFromLcid (LCID lcid, std::string &ret)
ret = GetLocaleElaboratedCodeFromLcidA (lcid);
}
-LCID LocaleCodeToLcidW (LPCWSTR localeCode)
+LCID LocaleCodeToLcidW (const std::wstring &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;
+#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)
+ try
+ {
+ BYTE buf [LOCALE_NAME_MAX_LENGTH * sizeof (WCHAR)] = {0};
+ int res = GetLocaleInfoEx (localeCode.c_str (), LOCALE_RETURN_NUMBER | LOCALE_ILANGUAGE, (LPWSTR)buf, LOCALE_NAME_MAX_LENGTH);
+ LCID lcid = *((LCID *)buf);
+ return lcid;
+ }
+ catch (const std::exception &e) {}
+ return LocaleNameToLCID (localeCode.c_str (), 0);
+#else
+ return LocaleNameToLCID (localeCode.c_str (), 0);
+#endif
}
-LCID LocaleCodeToLcidA (LPCSTR localeCode)
+LCID LocaleCodeToLcidA (const std::string &localeCode)
{
std::wstring lcWide = StringToWString (std::string (localeCode));
return LocaleCodeToLcidW (lcWide.c_str ());
@@ -157,7 +166,91 @@ std::string LcidToLocaleCodeA (LCID lcid, char divide = '-')
}
std::wstring LcidToLocaleCodeW (LCID lcid, WCHAR divide = L'-')
{
+#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)
+ try
+ {
+ WCHAR buf [LOCALE_NAME_MAX_LENGTH] = {0};
+ LCIDToLocaleName (lcid, buf, LOCALE_NAME_MAX_LENGTH, 0);
+ return buf;
+ }
+ catch (const std::exception &e) {}
return GetLocaleRestrictedCodeFromLcidW (lcid) + divide + GetLocaleElaboratedCodeFromLcidW (lcid);
+#else
+ return GetLocaleRestrictedCodeFromLcidW (lcid) + divide + GetLocaleElaboratedCodeFromLcidW (lcid);
+#endif
}
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
+std::string LcidToLocaleCode (LCID lcid, char divide = '-') { return LcidToLocaleCodeA (lcid, divide); }
+
+std::wstring GetUserDefaultLocaleName ()
+{
+#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)
+ try
+ {
+ WCHAR buf [LOCALE_NAME_MAX_LENGTH] = {0};
+ GetUserDefaultLocaleName (buf, LOCALE_NAME_MAX_LENGTH);
+ return buf;
+ }
+ catch (const std::exception &e) {}
+ return LcidToLocaleCodeW (GetUserDefaultLCID ());
+#else
+ return LcidToLocaleCodeW (GetUserDefaultLCID ());
+#endif
+}
+std::wstring GetSystemDefaultLocaleName ()
+{
+#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)
+ try
+ {
+ WCHAR buf [LOCALE_NAME_MAX_LENGTH] = {0};
+ GetSystemDefaultLocaleName (buf, LOCALE_NAME_MAX_LENGTH);
+ return buf;
+ }
+ catch (const std::exception &e) {}
+ return LcidToLocaleCodeW (GetSystemDefaultLCID ());
+#else
+ return LcidToLocaleCodeW (GetSystemDefaultLCID ());
+#endif
+}
+
+std::wstring GetComputerLocaleCodeW ()
+{
+#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)
+ {
+ try
+ {
+ {
+ LCID lcid = GetThreadLocale ();
+ std::wstring tmp = LcidToLocaleCodeW (lcid);
+ if (lcid && tmp.length () > 1) return tmp;
+ }
+ {
+ WCHAR buf [LOCALE_NAME_MAX_LENGTH] = {0};
+ GetUserDefaultLocaleName (buf, LOCALE_NAME_MAX_LENGTH);
+ if (lstrlenW (buf)) return buf;
+ }
+ {
+ WCHAR buf [LOCALE_NAME_MAX_LENGTH] = {0};
+ GetSystemDefaultLocaleName (buf, LOCALE_NAME_MAX_LENGTH);
+ return buf;
+ }
+ }
+ catch (const std::exception &e) {}
+ LCID lcid = GetThreadLocale ();
+ if (!lcid) lcid = GetUserDefaultLCID ();
+ if (!lcid) lcid = GetSystemDefaultLCID ();
+ return LcidToLocaleCodeW (lcid);
+ }
+#else
+ {
+ LCID lcid = GetThreadLocale ();
+ if (!lcid) lcid = GetUserDefaultLCID ();
+ if (!lcid) lcid = GetSystemDefaultLCID ();
+ return LcidToLocaleCodeW (lcid);
+ }
+#endif
+}
+bool LocaleNameCompare (const std::wstring &left, const std::wstring &right)
+{
+ return std::wnstring::equals (left, right) || LocaleCodeToLcidW (left) == LocaleCodeToLcidW (right);
+}
diff --git a/pkgread/pkgread.cpp b/pkgread/pkgread.cpp
index d01e03a..bfe1b99 100644
--- a/pkgread/pkgread.cpp
+++ b/pkgread/pkgread.cpp
@@ -5,6 +5,7 @@
#include "readobj.h"
#include "pkgread.h"
#include "localeex.h"
+#include "themeinfo.h"
#define ToHandleRead(_cpp_ptr_) reinterpret_cast (_cpp_ptr_)
#define ToPtrPackage(_cpp_ptr_) reinterpret_cast (_cpp_ptr_)
@@ -859,4 +860,313 @@ BOOL GetPackagePrerequisite (_In_ HPKGREAD hReader, _In_ LPCWSTR lpName, _Outptr
} break;
}
return FALSE;
-}
\ No newline at end of file
+}
+
+// Selector
+std::wnstring SelectLanguageSuitPackageNameByLocaleCode (std::map &in, const std::wstring &langcode, std::wnstring &output)
+{
+ output.clear ();
+ for (auto &it : in)
+ {
+ if (it.second.restype != appx_info::ResourceType::language) continue;
+ for (auto &it_s : it.second.resvalue.languages) if (LocaleNameCompare (it_s, langcode)) return output = it.first;
+ }
+ return output = L"";
+}
+std::wnstring SelectLanguageSuitPackageName (std::map &in, std::wnstring &output)
+{
+ output.clear ();
+ output = SelectLanguageSuitPackageNameByLocaleCode (in, GetComputerLocaleCodeW (), output);
+ if (output.empty ()) output = SelectLanguageSuitPackageNameByLocaleCode (in, L"en-US", output);
+ if (output.empty ())
+ {
+ for (auto &it : in)
+ {
+ if (it.second.pkgtype == APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE_APPLICATION)
+ {
+ output = it.first;
+ break;
+ }
+ }
+ }
+ if (output.empty ())
+ {
+ try { output = in.begin ()->first; }
+ catch (const std::exception &e) { output = L""; }
+ }
+ return output;
+}
+std::wnstring SelectScaleSuitPackageName (std::map &in, std::wnstring &output)
+{
+ output.clear ();
+ struct res_key_value
+ {
+ std::wnstring filename = L"";
+ uint32_t scale = 0;
+ res_key_value (const std::wstring &fpath = L"", uint32_t s = 0):
+ filename (fpath), scale (s) {}
+ };
+ std::vector rkv;
+ for (auto &it : in) if ((WORD)it.second.restype & (WORD)appx_info::ResourceType::scale)
+ {
+ for (auto &it_s : it.second.resvalue.scales)
+ {
+ if (!it_s) continue;
+ rkv.push_back (res_key_value (it.first, it_s));
+ }
+ }
+ std::sort (rkv.begin (), rkv.end (), [] (const res_key_value &a, const res_key_value &b) {
+ return a.scale < b.scale;
+ });
+ auto dpi = GetDPI ();
+ for (auto &it : rkv) if (it.scale > dpi) return output = it.filename;
+ if (output.empty ()) { for (auto it = rkv.rbegin (); it != rkv.rend (); ++ it) if (it->scale < dpi) return output = it->filename; }
+ if (output.empty ()) { for (auto &it : in) if (it.second.pkgtype == APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE_APPLICATION) return output = it.first; }
+ try { output = in.begin ()->first; }
+ catch (const std::exception &e) { output = L""; }
+ return output;
+}
+
+// File Stream
+HANDLE GetAppxFileFromAppxPackage (_In_ HPKGREAD hReader, _In_ LPCWSTR lpFileName)
+{
+ auto ptr = ToPtrPackage (hReader);
+ if (!ptr) return nullptr;
+ if (!lpFileName) return nullptr;
+ switch (ptr->type ())
+ {
+ case PackageType::single: {
+ auto reader = ptr->appx_reader ();
+ CComPtr afile;
+ if (FAILED (reader.payload_stream (lpFileName, &afile))) return nullptr;
+ IStream *istream = nullptr;
+ if (FAILED (afile->GetStream (&istream))) return nullptr;
+ else return istream;
+ } break;
+ case PackageType::bundle: {
+ auto bread = ptr->bundle_reader ();
+ CComPtr appfile;
+ if (FAILED (bread.random_application_package (&appfile))) return nullptr;
+ appxreader reader (appfile.p);
+ CComPtr afile;
+ if (FAILED (reader.payload_stream (lpFileName, &afile))) return nullptr;
+ IStream *istream = nullptr;
+ if (FAILED (afile->GetStream (&istream))) return nullptr;
+ else return istream;
+ } break;
+ }
+ return nullptr;
+}
+HANDLE GetAppxBundlePayloadPackageFile (_In_ HPKGREAD hReader, _In_ LPCWSTR lpFileName)
+{
+ auto ptr = ToPtrPackage (hReader);
+ if (!ptr) return nullptr;
+ if (!lpFileName) return nullptr;
+ if (ptr->type () == PackageType::bundle)
+ {
+ auto reader = ptr->bundle_reader ();
+ CComPtr iafile;
+ if (FAILED (reader.get_payload_package (lpFileName, &iafile))) return nullptr;
+ IStream *istream = nullptr;
+ if (FAILED (iafile->GetStream (&istream))) return nullptr;
+ else return istream;
+ }
+ else return nullptr;
+}
+HANDLE GetAppxPriFileStream (_In_ HPKGREAD hReader) { return GetAppxFileFromAppxPackage (hReader, L"resources.pri"); }
+HANDLE GetFileFromPayloadPackage (_In_ HANDLE hPackageStream, _In_ LPCWSTR lpFileName)
+{
+ if (!hPackageStream || !lpFileName) return nullptr;
+ IStream *ifs = (IStream *)hPackageStream;
+ CComPtr iappx;
+ if (FAILED (GetAppxPackageReader (ifs, &iappx))) return nullptr;
+ appxreader reader (iappx.p);
+ CComPtr iaf;
+ if (FAILED (reader.payload_stream (lpFileName, &iaf))) return nullptr;
+ IStream *istream = nullptr;
+ if (FAILED (iaf->GetStream (&istream))) return nullptr;
+ else return istream;
+}
+HANDLE GetPriFileFromPayloadPackage (_In_ HANDLE hPackageStream) { return GetFileFromPayloadPackage (hPackageStream, L"resources.pri"); }
+BOOL GetSuitablePackageFromBundle (_In_ HPKGREAD hReader, _Outptr_ HANDLE *pStreamForLang, _Outptr_ HANDLE *pStreamForScale)
+{
+ auto ptr = ToPtrPackage (hReader);
+ if (!ptr) return FALSE;
+ if (ptr->type () != PackageType::bundle) return FALSE;
+ if (pStreamForLang) *pStreamForLang = nullptr;
+ if (pStreamForScale) *pStreamForScale = nullptr;
+ auto bread = ptr->bundle_reader ();
+ auto pkgsinfo = bread.package_id_items ();
+ std::map mapfr;
+ pkgsinfo.resource_info (mapfr);
+ std::wnstring lf = L"", sf = L"";
+ SelectLanguageSuitPackageName (mapfr, lf);
+ SelectScaleSuitPackageName (mapfr, sf);
+ if (lf == sf)
+ {
+ WORD flag = (bool)pStreamForLang << 1 | (bool)pStreamForScale;
+ switch (flag)
+ {
+ case 0b01:
+ case 0b10:
+ case 0b11: {
+ IStream *file = nullptr;
+ CComPtr pread;
+ if (FAILED (bread.get_payload_package (lf, &pread))) return false;
+ if (FAILED (pread->GetStream (&file))) return false;
+ if (pStreamForLang) *pStreamForLang = file;
+ if (pStreamForScale) *pStreamForScale = file;
+ return true;
+ } break;
+ default:
+ case 0b00: {
+ CComPtr pread;
+ if (FAILED (bread.get_payload_package (lf, &pread))) return false;
+ CComPtr file = nullptr;
+ if (FAILED (pread->GetStream (&file))) return false;
+ else return true;
+ } break;
+ }
+ }
+ else
+ {
+ {
+ CComPtr reslangpkg;
+ if (FAILED (bread.get_payload_package (lf, &reslangpkg))) return false;
+ if (pStreamForLang)
+ {
+ IStream *file = nullptr;
+ if (FAILED (reslangpkg->GetStream (&file))) return false;
+ *pStreamForLang = file;
+ }
+ else
+ {
+ CComPtr file;
+ if (FAILED (reslangpkg->GetStream (&file))) return false;
+ }
+ }
+ {
+ CComPtr resscalepkg;
+ if (FAILED (bread.get_payload_package (sf, &resscalepkg))) return false;
+ if (pStreamForScale)
+ {
+ IStream *file = nullptr;
+ if (FAILED (resscalepkg->GetStream (&file))) return false;
+ *pStreamForScale = file;
+ }
+ else
+ {
+ CComPtr file;
+ if (FAILED (resscalepkg->GetStream (&file))) return false;
+ }
+ }
+ }
+ return true;
+}
+ULONG DestroyAppxFileStream (_In_ HANDLE hFileStream)
+{
+ if (!hFileStream) return 0;
+ IStream *ptr = reinterpret_cast (hFileStream);
+ if (!ptr) return 0;
+ return ptr->Release ();
+}
+HANDLE GetAppxBundleApplicationPackageFile (_In_ HPKGREAD hReader)
+{
+ if (!hReader) return nullptr;
+ auto ptr = ToPtrPackage (hReader);
+ if (!ptr) return nullptr;
+ switch (ptr->type ())
+ {
+ case PackageType::single: {
+ return nullptr;
+ } break;
+ case PackageType::bundle: {
+ auto bread = ptr->bundle_reader ();
+ IStream *ipf = nullptr;
+ if (FAILED (bread.random_application_package (&ipf))) return nullptr;
+ else return ipf;
+ } break;
+ }
+ return nullptr;
+}
+
+std::wstring GetMimeTypeFromStream (IStream *filestream)
+{
+ if (!filestream) return L"";
+ LARGE_INTEGER liZero = {0};
+ filestream->Seek (liZero, STREAM_SEEK_SET, nullptr);
+ BYTE buffer [256] = {0};
+ ULONG bytesRead = 0;
+ HRESULT hr = filestream->Read (buffer, sizeof (buffer), &bytesRead);
+ filestream->Seek (liZero, STREAM_SEEK_SET, nullptr);
+ if (FAILED (hr) || bytesRead == 0) return L"";
+ LPWSTR lpMime = nullptr;
+ raii relt ([&lpMime] () {
+ if (lpMime) CoTaskMemFree (lpMime);
+ lpMime = nullptr;
+ });
+ std::wstring mime;
+ hr = FindMimeFromData (
+ nullptr, // pBC
+ nullptr, // URL (unknown)
+ buffer, // data buffer
+ bytesRead, // data size
+ nullptr, // proposed MIME
+ FMFD_RETURNUPDATEDIMGMIMES |
+ FMFD_IGNOREMIMETEXTPLAIN |
+ FMFD_URLASFILENAME,
+ &lpMime, // result
+ 0 // reserved
+ );
+ if (SUCCEEDED (hr) && lpMime) mime = lpMime;
+ if (mime.empty ())
+ {
+ if (bytesRead >= 8 && memcmp (buffer, "\x89PNG\r\n\x1A\n", 8) == 0) mime = L"image/png";
+ else if (bytesRead >= 3 && buffer [0] == 0xFF && buffer [1] == 0xD8) mime = L"image/jpeg";
+ else if (bytesRead >= 6 && memcmp (buffer, "GIF89a", 6) == 0) mime = L"image/gif";
+ else if (bytesRead >= 2 && buffer [0] == 'B' && buffer [1] == 'M') mime = L"image/bmp";
+ else if (bytesRead >= 12 && memcmp (buffer, "RIFF", 4) == 0 && memcmp (buffer + 8, "WEBP", 4) == 0) mime = L"image/webp";
+ else if (bytesRead >= 4 && memcmp (buffer, "\x00\x00\x01\x00", 4) == 0) mime = L"image/x-icon";
+ else mime = L"application/octet-stream";
+ }
+ return mime;
+}
+std::wstring GetBase64StringFromStreamW (IStream *ifile)
+{
+ if (!ifile) return L"";
+ IStream *&pStream = ifile;
+ LARGE_INTEGER liZero = {};
+ pStream->Seek (liZero, STREAM_SEEK_SET, nullptr);
+ STATSTG statstg;
+ pStream->Stat (&statstg, STATFLAG_NONAME);
+ ULARGE_INTEGER uliSize = statstg.cbSize;
+ std::vector buffer (uliSize.QuadPart);
+ ULONG bytesRead;
+ pStream->Read (buffer.data (), static_cast (buffer.size ()), &bytesRead);
+ DWORD base64Size = 0;
+ if (!CryptBinaryToStringW (buffer.data (), bytesRead, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, nullptr, &base64Size)) return nullptr;
+ std::vector base64Buffer (base64Size + 1);
+ if (!CryptBinaryToStringW (buffer.data (), bytesRead, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, base64Buffer.data (), &base64Size)) return nullptr;
+ pStream->Seek (liZero, STREAM_SEEK_SET, nullptr);
+ return std::wstring (base64Buffer.data ());
+}
+LPWSTR StreamToBase64W (_In_ HANDLE hFileStream, _Out_writes_ (dwCharCount) LPWSTR lpMimeBuf, _In_ DWORD dwCharCount, _Outptr_ LPWSTR *lpBase64Head)
+{
+ IStream *ifs = (IStream *)hFileStream;
+ if (!ifs) return nullptr;
+ LPWSTR retptr = nullptr;
+ std::wstring ret = L"";
+ std::wstring mime = GetMimeTypeFromStream (ifs);
+ auto &dwBufSize = dwCharCount;
+ if (lpMimeBuf)
+ {
+ ZeroMemory (lpMimeBuf, sizeof (WCHAR) * dwBufSize);
+ wcsncpy_s (lpMimeBuf, dwBufSize, mime.c_str (), _TRUNCATE);
+ }
+ ret += L"data:" + mime + L";base64,";
+ size_t head = ret.length ();
+ ret += GetBase64StringFromStreamW (ifs);
+ retptr = _wcsdup (ret.c_str ());
+ if (lpBase64Head) *lpBase64Head = retptr + head;
+ return retptr;
+}
diff --git a/pkgread/pkgread.h b/pkgread/pkgread.h
index 4f09cd6..79a6898 100644
--- a/pkgread/pkgread.h
+++ b/pkgread/pkgread.h
@@ -14,7 +14,7 @@
#ifdef __cplusplus
#define _DEFAULT_INIT_VALUE_(_init_value_) = _init_value_
-#ifdef PKGREAD_EXPORTS
+#ifndef PKGREAD_EXPORTS
#define _DEFAULT_INIT_VALUE_FORFUNC_(_init_value_) = _init_value_
#else
#define _DEFAULT_INIT_VALUE_FORFUNC_(_init_value_)
@@ -252,6 +252,36 @@ extern "C"
#define GetPackagePrerequisiteOsMinVersion(_In_hReader_, _Outptr_pVerRet_) GetPackagePrerequisite (_In_hReader_, PKG_PREREQUISITE_OS_MIN_VERSION, _Outptr_pVerRet_)
#define GetPackagePrerequisiteOsMaxVersionTested(_In_hReader_, _Outptr_pVerRet_) GetPackagePrerequisite (_In_hReader_, PKG_PREREQUISITE_OS_MAX_VERSION_TESTED, _Outptr_pVerRet_)
+ // File Stream
+ // Appx лȡ Appx еļļ
+ // עֻȡ Payloads ļṩ Footprint ļ
+ // AppxBundle һӦðȡļ
+ PKGREAD_API HANDLE GetAppxFileFromAppxPackage (_In_ HPKGREAD hReader, _In_ LPCWSTR lpFileName);
+ // AppxBundle лȡ Appx Ӱļ
+ PKGREAD_API HANDLE GetAppxBundlePayloadPackageFile (_In_ HPKGREAD hReader, _In_ LPCWSTR lpFileName);
+ // Appx лȡ Appx Pri ļ
+ // AppxBundle һӦðȡ Pri ļ
+ PKGREAD_API HANDLE GetAppxPriFileStream (_In_ HPKGREAD hReader);
+ // AppxBundle лȡӰļȡеļ
+ // עֻȡ Payloads ļṩ Footprint ļ
+ PKGREAD_API HANDLE GetFileFromPayloadPackage (_In_ HANDLE hPackageStream, _In_ LPCWSTR lpFileName);
+ // AppxBundle лȡӰļȡ Pri ļ
+ PKGREAD_API HANDLE GetPriFileFromPayloadPackage (_In_ HANDLE hPackageStream);
+ // AppxBundle лȡʵİָԴʡ
+ // һڷصIJָǷصԺʵѡڶڷصIJǷصԴ
+ // ָĶͬһôصĶͬһָ롣
+ // Appx ļֱӷؼ١
+ PKGREAD_API BOOL GetSuitablePackageFromBundle (_In_ HPKGREAD hReader, _Outptr_ HANDLE *pStreamForLang, _Outptr_ HANDLE *pStreamForScale);
+ // ļͨͷš
+ PKGREAD_API ULONG DestroyAppxFileStream (_In_ HANDLE hFileStream);
+ // תļת Data URLתʹͼƬ
+ // ע⣺dwCharCount ָ lpMimeBuf Ŀַ WCHAR lpMimeBuf [dwCharCount]ʵʿֽ
+ // صķǿָҪͨ free ͷšlpBase64Head ص Base64 ݣΪָָIJ֡
+ // ַΪ data:text/plain;base64,SGVsbG8sIFdvcmxkIQ%3D%3D
+ // ô lpBase64Head ָڡbase64,ĵһַ
+ PKGREAD_API LPWSTR StreamToBase64W (_In_ HANDLE hFileStream, _Out_writes_ (dwCharCount) LPWSTR lpMimeBuf, _In_ DWORD dwCharCount, _Outptr_ LPWSTR *lpBase64Head);
+ // ȡ AppxBundle еӦðļͨ DestroyAppxFileStream ١
+ PKGREAD_API HANDLE GetAppxBundleApplicationPackageFile (_In_ HPKGREAD hReader);
#ifdef _DEFAULT_INIT_VALUE_
#undef _DEFAULT_INIT_VALUE_
#endif
@@ -262,24 +292,142 @@ extern "C"
}
#endif
-#if defined (__cplusplus) && !defined (PKGREAD_EXPORTS)
+#if defined (__cplusplus)
#include
#include
#include
@@ -122,6 +123,7 @@
true
true
true
+ urlmon.lib;crypt32.lib;%(AdditionalDependencies)
@@ -145,18 +147,18 @@
-
-
+
+
@@ -185,6 +187,9 @@
+
+
+
diff --git a/pkgread/pkgread.vcxproj.filters b/pkgread/pkgread.vcxproj.filters
index 0ff98ee..4b5706c 100644
--- a/pkgread/pkgread.vcxproj.filters
+++ b/pkgread/pkgread.vcxproj.filters
@@ -33,9 +33,6 @@
头文件
-
- 头文件
-
头文件
@@ -54,7 +51,10 @@
头文件
-
+
+ 头文件
+
+
头文件
@@ -72,4 +72,9 @@
+
+
+ 资源文件
+
+
\ No newline at end of file
diff --git a/pkgread/readobj.h b/pkgread/readobj.h
index 5580e60..885e109 100644
--- a/pkgread/readobj.h
+++ b/pkgread/readobj.h
@@ -209,7 +209,6 @@ template class com_info_quote
private:
IComInterface &icom = nullptr;
protected:
- ComInterface *pointer () const noexcept { return icom; }
template std::wstring get (_In_ Fn func) const
{
if (!icom) return L"";
@@ -254,6 +253,7 @@ template class com_info_quote
com_info_quote (com_info_quote &&) noexcept = default;
com_info_quote &operator = (com_info_quote &&) noexcept = default;
bool valid () const { return !!icom; }
+ ComInterface *pointer () const noexcept { return icom; }
};
namespace appx_info
{
@@ -703,6 +703,34 @@ namespace appx_info
}
UINT64 size () const { return get (&Interface::GetSize); }
};
+ enum class ResourceType
+ {
+ unknown = 0b00,
+ language = 0b01,
+ scale = 0b10,
+ both = 0b11
+ };
+ struct resource
+ {
+ ResourceType restype = ResourceType::unknown;
+ APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE pkgtype = APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE_APPLICATION;
+ struct resource_content
+ {
+ std::vector languages;
+ std::vector scales;
+ resource_content (const std::vector &langs): languages (langs) {}
+ resource_content (const std::vector &ss): scales (ss) {}
+ resource_content (const std::vector &langs, const std::vector &ss): languages (langs), scales (ss) {}
+ resource_content () = default;
+ } resvalue;
+ resource (const std::vector &languages):
+ restype (ResourceType::language), resvalue (languages) {}
+ resource (const std::vector &ss):
+ restype (ResourceType::scale), resvalue (ss) {}
+ resource (const std::vector &langs, const std::vector &ss):
+ restype (ResourceType::both), resvalue (langs, ss) {}
+ resource (): restype (ResourceType::unknown), resvalue () {}
+ };
class appx_iditems: virtual public com_info
{
using Base = com_info ;
@@ -777,6 +805,33 @@ namespace appx_info
}
return cnt;
}
+ size_t resource_info (std::map &output) const
+ {
+ output.clear ();
+ std::vector items;
+ enumerate (items);
+ for (auto &it : items)
+ {
+ std::wnstring fpath = it.file_name ();
+ auto qres = it.qualified_resources ();
+ std::vector langs;
+ std::vector scales;
+ qres.qualified_resources (&langs, &scales);
+ std::vector langs_n;
+ for (auto &it_l : langs) langs_n.push_back (it_l);
+ BYTE status = (bool)langs_n.size () << 1 | (bool)scales.size ();
+ switch (status)
+ {
+ case 0b01: output [fpath] = resource (scales); break;
+ case 0b10: output [fpath] = resource (langs_n); break;
+ case 0b11: output [fpath] = resource (langs_n, scales); break;
+ default:
+ case 0b00: output [fpath] = resource (); break;
+ }
+ output [fpath].pkgtype = it.type ();
+ }
+ return output.size ();
+ }
};
}
class appxreader: virtual public com_info_quote
@@ -1029,6 +1084,98 @@ class bundlereader: virtual public com_info_quote
if (FAILED (hr)) return hr;
return GetAppxPackageReader (ist, output);
}
+ HRESULT random_application_package (_Outptr_ IAppxFile **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;
+ return get_payload_package (fname, output);
+ }
+ HRESULT random_resource_package (_Outptr_ IAppxFile **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;
+ return hr = get_payload_package (fname, output);
+ }
+ HRESULT random_application_package (_Outptr_ IStream **output) const
+ {
+ CComPtr iaf;
+ HRESULT hr = S_OK;
+ if (FAILED (hr = random_application_package (&iaf))) return hr;
+ return iaf->GetStream (output);
+ }
+ HRESULT random_resource_package (_Outptr_ IStream **output) const
+ {
+ CComPtr iaf;
+ HRESULT hr = S_OK;
+ if (FAILED (hr = random_resource_package (&iaf))) return hr;
+ return iaf->GetStream (output);
+ }
size_t application_packages (std::function callback) const
{
CComPtr iditems;
diff --git a/pkgread/resource.h b/pkgread/resource1.h
similarity index 100%
rename from pkgread/resource.h
rename to pkgread/resource1.h
diff --git a/pkgread/stdafx.h b/pkgread/stdafx.h
index b4e958f..97be4a1 100644
--- a/pkgread/stdafx.h
+++ b/pkgread/stdafx.h
@@ -23,4 +23,13 @@
#include
#include
#include
-#include
\ No newline at end of file
+#include
+#include
+#include
+
+#ifdef max
+#undef max
+#endif
+#ifdef min
+#undef min
+#endif
\ No newline at end of file
diff --git a/pkgread/themeinfo.h b/pkgread/themeinfo.h
new file mode 100644
index 0000000..8d3c712
--- /dev/null
+++ b/pkgread/themeinfo.h
@@ -0,0 +1,40 @@
+#pragma once
+#include
+
+bool IsHighContrastEnabled ()
+{
+ HIGHCONTRAST hc = {sizeof (HIGHCONTRAST)};
+ if (SystemParametersInfo (SPI_GETHIGHCONTRAST, sizeof (hc), &hc, 0)) return (hc.dwFlags & HCF_HIGHCONTRASTON) != 0;
+ return false;
+}
+enum class HighContrastTheme
+{
+ None,
+ Black,
+ White,
+ Other
+};
+HighContrastTheme GetHighContrastTheme ()
+{
+ HIGHCONTRAST hc = {sizeof (HIGHCONTRAST)};
+ if (!SystemParametersInfo (SPI_GETHIGHCONTRAST, sizeof (hc), &hc, 0)) return HighContrastTheme::None;
+ if (!(hc.dwFlags & HCF_HIGHCONTRASTON)) return HighContrastTheme::None;
+ COLORREF bgColor = GetSysColor (COLOR_WINDOW);
+ COLORREF textColor = GetSysColor (COLOR_WINDOWTEXT);
+ int brightnessBg = (GetRValue (bgColor) + GetGValue (bgColor) + GetBValue (bgColor)) / 3;
+ int brightnessText = (GetRValue (textColor) + GetGValue (textColor) + GetBValue (textColor)) / 3;
+ if (brightnessBg < brightnessText) return HighContrastTheme::Black;
+ else if (brightnessBg > brightnessText) return HighContrastTheme::White;
+ else return HighContrastTheme::Other;
+}
+int GetDPI ()
+{
+ HDC hDC = GetDC (NULL);
+ int DPI_A = (int)(((double)GetDeviceCaps (hDC, 118) / (double)GetDeviceCaps (hDC, 8)) * 100);
+ int DPI_B = (int)(((double)GetDeviceCaps (hDC, 88) / 96) * 100);
+ ReleaseDC (NULL, hDC);
+ if (DPI_A == 100) return DPI_B;
+ else if (DPI_B == 100) return DPI_A;
+ else if (DPI_A == DPI_B) return DPI_A;
+ else return 0;
+}