From 3a70be9491b0c6dbee3945112feec5aac487ab23 Mon Sep 17 00:00:00 2001 From: Bruce Date: Wed, 19 Feb 2025 21:09:40 +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 --- AppInstaller.sln | 179 ++ AppInstaller/AppInstaller.rc | 529 +++++ AppInstaller/AppInstaller.vcxproj | 333 +++ AppInstaller/AppInstaller.vcxproj.filters | 178 ++ AppInstaller/base64logo.h | 291 +++ AppInstaller/initread.h | 194 ++ AppInstaller/localeex.h | 111 + AppInstaller/mainwnd.cpp | 1464 ++++++++++++ AppInstaller/pkgcode.h | 2062 +++++++++++++++++ AppInstaller/pkginfo.h | 196 ++ AppInstaller/priread.h | 377 +++ AppInstaller/res/Button/Large/blank.png | Bin 0 -> 1873 bytes AppInstaller/res/Button/Large/blank_light.png | Bin 0 -> 1928 bytes AppInstaller/res/Button/Large/blank_press.png | Bin 0 -> 1928 bytes .../res/Button/Large/cancel_window_light.png | Bin 0 -> 2142 bytes .../res/Button/Large/cancel_window_normal.png | Bin 0 -> 1776 bytes .../res/Button/Large/cancel_window_press.png | Bin 0 -> 2146 bytes AppInstaller/res/Button/Large/max_light.png | Bin 0 -> 228 bytes AppInstaller/res/Button/Large/max_normal.png | Bin 0 -> 1466 bytes AppInstaller/res/Button/Large/max_press.png | Bin 0 -> 227 bytes .../res/Button/Large/max_trans_normal.png | Bin 0 -> 1685 bytes AppInstaller/res/Button/Large/min_light.png | Bin 0 -> 214 bytes AppInstaller/res/Button/Large/min_normal.png | Bin 0 -> 1880 bytes AppInstaller/res/Button/Large/min_press.png | Bin 0 -> 213 bytes .../res/Button/Large/min_trans_normal.png | Bin 0 -> 1880 bytes .../res/Button/Large/restore_light.png | Bin 0 -> 243 bytes .../res/Button/Large/restore_normal.png | Bin 0 -> 1473 bytes .../res/Button/Large/restore_press.png | Bin 0 -> 242 bytes .../res/Button/Large/restore_trans_normal.png | Bin 0 -> 1692 bytes AppInstaller/res/Button/Normal/blank.png | Bin 0 -> 1858 bytes .../res/Button/Normal/blank_light.png | Bin 0 -> 1904 bytes .../res/Button/Normal/blank_press.png | Bin 0 -> 1904 bytes .../res/Button/Normal/cancel_back.png | Bin 0 -> 1712 bytes .../res/Button/Normal/cancel_light.png | Bin 0 -> 1921 bytes .../res/Button/Normal/cancel_press.png | Bin 0 -> 1921 bytes AppInstaller/res/Button/Normal/max_back.png | Bin 0 -> 1449 bytes AppInstaller/res/Button/Normal/max_light.png | Bin 0 -> 1869 bytes AppInstaller/res/Button/Normal/max_press.png | Bin 0 -> 1869 bytes AppInstaller/res/Button/Normal/min_back.png | Bin 0 -> 1443 bytes AppInstaller/res/Button/Normal/min_light.png | Bin 0 -> 1864 bytes AppInstaller/res/Button/Normal/min_press.png | Bin 0 -> 1864 bytes .../res/Button/Normal/restore_back.png | Bin 0 -> 1450 bytes .../res/Button/Normal/restore_light.png | Bin 0 -> 1873 bytes .../res/Button/Normal/restore_press.png | Bin 0 -> 1873 bytes AppInstaller/res/Fonts/IDR_SETUP_FONT.TTF | Bin 0 -> 89344 bytes AppInstaller/res/Icons/FileIcon.ico | Bin 0 -> 53039 bytes AppInstaller/res/Icons/IconColor.ico | Bin 0 -> 188462 bytes AppInstaller/res/Icons/IconTitleBar.ico | Bin 0 -> 412402 bytes AppInstaller/res/Icons/IconWhite.ico | Bin 0 -> 156504 bytes AppInstaller/res/Icons/Main.ico | Bin 0 -> 35596 bytes AppInstaller/res/Pictures/Trans.png | Bin 0 -> 6384 bytes AppInstaller/res/Pictures/Trans_old.png | Bin 0 -> 1988 bytes AppInstaller/res/icon.ico | Bin 0 -> 7406 bytes AppInstaller/res/manifest.xml | 25 + AppInstaller/res2.h | 156 ++ AppInstaller/resource.h | 162 ++ AppLauncher/AppLauncher.cpp | 31 + AppLauncher/AppLauncher.h | 13 + AppLauncher/AppLauncher.vcxproj | 250 ++ AppLauncher/AppLauncher.vcxproj.filters | 42 + AppLauncher/ReadMe.txt | 30 + AppLauncher/dllmain.cpp | 19 + AppLauncher/stdafx.cpp | 8 + AppLauncher/stdafx.h | 25 + AppLauncher/targetver.h | 8 + Base64Img/Base64Img.cpp | 34 + Base64Img/Base64Img.h | 16 + Base64Img/Base64Img.vcxproj | 254 ++ Base64Img/Base64Img.vcxproj.filters | 42 + Base64Img/ReadMe.txt | 30 + Base64Img/dllmain.cpp | 19 + Base64Img/stdafx.cpp | 8 + Base64Img/stdafx.h | 28 + Base64Img/targetver.h | 8 + CertificateManager/CertificateManager.cpp | 629 +++++ CertificateManager/CertificateManager.h | 18 + CertificateManager/CertificateManager.vcxproj | 253 ++ .../CertificateManager.vcxproj.filters | 42 + CertificateManager/ReadMe.txt | 30 + CertificateManager/dllmain.cpp | 19 + CertificateManager/stdafx.cpp | 8 + CertificateManager/stdafx.h | 21 + CertificateManager/targetver.h | 8 + PackageAdd/PackageAdd.csproj | 58 + PackageAdd/PackageInstaller.cs | 70 + PackageAdd/Properties/AssemblyInfo.cs | 36 + PackageManager/PackageManager.cpp | 82 + PackageManager/PackageManager.h | 38 + PackageManager/PackageManager.vcxproj | 182 ++ PackageManager/PackageManager.vcxproj.filters | 42 + PackageManager/ReadMe.txt | 30 + PackageManager/dllmain.cpp | 19 + PackageManager/stdafx.cpp | 8 + PackageManager/stdafx.h | 25 + PackageManager/targetver.h | 8 + PackageManagerAdd/AddPackageSample.cpp | 34 + PackageManagerAdd/AddPackageSample.sln | 20 + PackageManagerAdd/AddPackageSample.vcxproj | 168 ++ PackageManagerAdd/PackageManager.h | 26 + PackageManagerAdd/README.txt | 39 + PackageManagerAdd/pkgaddcode.cpp | 86 + PackageManagerAdd/stdafx.h | 12 + PriReader/AddPackageSample.cpp | 34 + PriReader/AddPackageSample.vcxproj | 103 + PriReader/PriReader.cpp | 84 + PriReader/PriReader.h | 11 + PriReader/PriReader.sln | 20 + PriReader/README.txt | 39 + PriReader/stdafx.h | 18 + PriReader2/PriReader2.cpp | 1879 +++++++++++++++ PriReader2/PriReader2.h | 69 + PriReader2/PriReader2.vcxproj | 265 +++ PriReader2/PriReader2.vcxproj.filters | 48 + PriReader2/ReadMe.txt | 30 + PriReader2/dllmain.cpp | 19 + PriReader2/localeex.h | 108 + PriReader2/packages.config | 4 + PriReader2/stdafx.cpp | 8 + PriReader2/stdafx.h | 30 + PriReader2/targetver.h | 8 + README.md | 2 + ShoutcutCreater/AddPackageSample.cpp | 34 + ShoutcutCreater/README.txt | 39 + ShoutcutCreater/ShortcutCreater.cpp | 46 + ShoutcutCreater/ShortcutCreater.h | 10 + ShoutcutCreater/ShortcutCreater.sln | 22 + ShoutcutCreater/ToastNotification.vcxproj | 101 + ShoutcutCreater/stdafx.h | 5 + ToastNotification/AddPackageSample.cpp | 34 + ToastNotification/README.txt | 39 + ToastNotification/ToastNotification.cpp | 226 ++ ToastNotification/ToastNotification.h | 17 + ToastNotification/ToastNotification.sln | 20 + ToastNotification/ToastNotification.vcxproj | 170 ++ ToastNotification/stdafx.h | 23 + 135 files changed, 12698 insertions(+) create mode 100644 AppInstaller.sln create mode 100644 AppInstaller/AppInstaller.rc create mode 100644 AppInstaller/AppInstaller.vcxproj create mode 100644 AppInstaller/AppInstaller.vcxproj.filters create mode 100644 AppInstaller/base64logo.h create mode 100644 AppInstaller/initread.h create mode 100644 AppInstaller/localeex.h create mode 100644 AppInstaller/mainwnd.cpp create mode 100644 AppInstaller/pkgcode.h create mode 100644 AppInstaller/pkginfo.h create mode 100644 AppInstaller/priread.h create mode 100644 AppInstaller/res/Button/Large/blank.png create mode 100644 AppInstaller/res/Button/Large/blank_light.png create mode 100644 AppInstaller/res/Button/Large/blank_press.png create mode 100644 AppInstaller/res/Button/Large/cancel_window_light.png create mode 100644 AppInstaller/res/Button/Large/cancel_window_normal.png create mode 100644 AppInstaller/res/Button/Large/cancel_window_press.png create mode 100644 AppInstaller/res/Button/Large/max_light.png create mode 100644 AppInstaller/res/Button/Large/max_normal.png create mode 100644 AppInstaller/res/Button/Large/max_press.png create mode 100644 AppInstaller/res/Button/Large/max_trans_normal.png create mode 100644 AppInstaller/res/Button/Large/min_light.png create mode 100644 AppInstaller/res/Button/Large/min_normal.png create mode 100644 AppInstaller/res/Button/Large/min_press.png create mode 100644 AppInstaller/res/Button/Large/min_trans_normal.png create mode 100644 AppInstaller/res/Button/Large/restore_light.png create mode 100644 AppInstaller/res/Button/Large/restore_normal.png create mode 100644 AppInstaller/res/Button/Large/restore_press.png create mode 100644 AppInstaller/res/Button/Large/restore_trans_normal.png create mode 100644 AppInstaller/res/Button/Normal/blank.png create mode 100644 AppInstaller/res/Button/Normal/blank_light.png create mode 100644 AppInstaller/res/Button/Normal/blank_press.png create mode 100644 AppInstaller/res/Button/Normal/cancel_back.png create mode 100644 AppInstaller/res/Button/Normal/cancel_light.png create mode 100644 AppInstaller/res/Button/Normal/cancel_press.png create mode 100644 AppInstaller/res/Button/Normal/max_back.png create mode 100644 AppInstaller/res/Button/Normal/max_light.png create mode 100644 AppInstaller/res/Button/Normal/max_press.png create mode 100644 AppInstaller/res/Button/Normal/min_back.png create mode 100644 AppInstaller/res/Button/Normal/min_light.png create mode 100644 AppInstaller/res/Button/Normal/min_press.png create mode 100644 AppInstaller/res/Button/Normal/restore_back.png create mode 100644 AppInstaller/res/Button/Normal/restore_light.png create mode 100644 AppInstaller/res/Button/Normal/restore_press.png create mode 100644 AppInstaller/res/Fonts/IDR_SETUP_FONT.TTF create mode 100644 AppInstaller/res/Icons/FileIcon.ico create mode 100644 AppInstaller/res/Icons/IconColor.ico create mode 100644 AppInstaller/res/Icons/IconTitleBar.ico create mode 100644 AppInstaller/res/Icons/IconWhite.ico create mode 100644 AppInstaller/res/Icons/Main.ico create mode 100644 AppInstaller/res/Pictures/Trans.png create mode 100644 AppInstaller/res/Pictures/Trans_old.png create mode 100644 AppInstaller/res/icon.ico create mode 100644 AppInstaller/res/manifest.xml create mode 100644 AppInstaller/res2.h create mode 100644 AppInstaller/resource.h create mode 100644 AppLauncher/AppLauncher.cpp create mode 100644 AppLauncher/AppLauncher.h create mode 100644 AppLauncher/AppLauncher.vcxproj create mode 100644 AppLauncher/AppLauncher.vcxproj.filters create mode 100644 AppLauncher/ReadMe.txt create mode 100644 AppLauncher/dllmain.cpp create mode 100644 AppLauncher/stdafx.cpp create mode 100644 AppLauncher/stdafx.h create mode 100644 AppLauncher/targetver.h create mode 100644 Base64Img/Base64Img.cpp create mode 100644 Base64Img/Base64Img.h create mode 100644 Base64Img/Base64Img.vcxproj create mode 100644 Base64Img/Base64Img.vcxproj.filters create mode 100644 Base64Img/ReadMe.txt create mode 100644 Base64Img/dllmain.cpp create mode 100644 Base64Img/stdafx.cpp create mode 100644 Base64Img/stdafx.h create mode 100644 Base64Img/targetver.h create mode 100644 CertificateManager/CertificateManager.cpp create mode 100644 CertificateManager/CertificateManager.h create mode 100644 CertificateManager/CertificateManager.vcxproj create mode 100644 CertificateManager/CertificateManager.vcxproj.filters create mode 100644 CertificateManager/ReadMe.txt create mode 100644 CertificateManager/dllmain.cpp create mode 100644 CertificateManager/stdafx.cpp create mode 100644 CertificateManager/stdafx.h create mode 100644 CertificateManager/targetver.h create mode 100644 PackageAdd/PackageAdd.csproj create mode 100644 PackageAdd/PackageInstaller.cs create mode 100644 PackageAdd/Properties/AssemblyInfo.cs create mode 100644 PackageManager/PackageManager.cpp create mode 100644 PackageManager/PackageManager.h create mode 100644 PackageManager/PackageManager.vcxproj create mode 100644 PackageManager/PackageManager.vcxproj.filters create mode 100644 PackageManager/ReadMe.txt create mode 100644 PackageManager/dllmain.cpp create mode 100644 PackageManager/stdafx.cpp create mode 100644 PackageManager/stdafx.h create mode 100644 PackageManager/targetver.h create mode 100644 PackageManagerAdd/AddPackageSample.cpp create mode 100644 PackageManagerAdd/AddPackageSample.sln create mode 100644 PackageManagerAdd/AddPackageSample.vcxproj create mode 100644 PackageManagerAdd/PackageManager.h create mode 100644 PackageManagerAdd/README.txt create mode 100644 PackageManagerAdd/pkgaddcode.cpp create mode 100644 PackageManagerAdd/stdafx.h create mode 100644 PriReader/AddPackageSample.cpp create mode 100644 PriReader/AddPackageSample.vcxproj create mode 100644 PriReader/PriReader.cpp create mode 100644 PriReader/PriReader.h create mode 100644 PriReader/PriReader.sln create mode 100644 PriReader/README.txt create mode 100644 PriReader/stdafx.h create mode 100644 PriReader2/PriReader2.cpp create mode 100644 PriReader2/PriReader2.h create mode 100644 PriReader2/PriReader2.vcxproj create mode 100644 PriReader2/PriReader2.vcxproj.filters create mode 100644 PriReader2/ReadMe.txt create mode 100644 PriReader2/dllmain.cpp create mode 100644 PriReader2/localeex.h create mode 100644 PriReader2/packages.config create mode 100644 PriReader2/stdafx.cpp create mode 100644 PriReader2/stdafx.h create mode 100644 PriReader2/targetver.h create mode 100644 README.md create mode 100644 ShoutcutCreater/AddPackageSample.cpp create mode 100644 ShoutcutCreater/README.txt create mode 100644 ShoutcutCreater/ShortcutCreater.cpp create mode 100644 ShoutcutCreater/ShortcutCreater.h create mode 100644 ShoutcutCreater/ShortcutCreater.sln create mode 100644 ShoutcutCreater/ToastNotification.vcxproj create mode 100644 ShoutcutCreater/stdafx.h create mode 100644 ToastNotification/AddPackageSample.cpp create mode 100644 ToastNotification/README.txt create mode 100644 ToastNotification/ToastNotification.cpp create mode 100644 ToastNotification/ToastNotification.h create mode 100644 ToastNotification/ToastNotification.sln create mode 100644 ToastNotification/ToastNotification.vcxproj create mode 100644 ToastNotification/stdafx.h diff --git a/AppInstaller.sln b/AppInstaller.sln new file mode 100644 index 0000000..39e9805 --- /dev/null +++ b/AppInstaller.sln @@ -0,0 +1,179 @@ + +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", "AppInstaller\AppInstaller.vcxproj", "{D417C165-3F17-40C4-8C7B-0F5AACEF62C5}" + ProjectSection(ProjectDependencies) = postProject + {B897969C-6EA9-4DFC-B7E0-94F1C6D94856} = {B897969C-6EA9-4DFC-B7E0-94F1C6D94856} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AppLauncher", "AppLauncher\AppLauncher.vcxproj", "{285130BC-CBF1-4C7A-A28D-6F5EE6C68384}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PackageManager", "PackageManagerAdd\AddPackageSample.vcxproj", "{59131AB7-2A7D-9A09-8223-174C3F5E0F57}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Base64Img", "Base64Img\Base64Img.vcxproj", "{911EDC63-DB20-4D61-9420-583A1C35427F}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ToastNotification", "ToastNotification\ToastNotification.vcxproj", "{E10C6272-B876-4DC6-9E13-7CA646863B50}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PriReader2", "PriReader2\PriReader2.vcxproj", "{B897969C-6EA9-4DFC-B7E0-94F1C6D94856}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CertificateManager", "CertificateManager\CertificateManager.vcxproj", "{22702832-C3FD-48E5-BC7D-3879CA50A2ED}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|ARM = Debug|ARM + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|ARM = Release|ARM + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D417C165-3F17-40C4-8C7B-0F5AACEF62C5}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {D417C165-3F17-40C4-8C7B-0F5AACEF62C5}.Debug|Any CPU.Build.0 = Debug|Win32 + {D417C165-3F17-40C4-8C7B-0F5AACEF62C5}.Debug|ARM.ActiveCfg = Debug|ARM + {D417C165-3F17-40C4-8C7B-0F5AACEF62C5}.Debug|ARM.Build.0 = Debug|ARM + {D417C165-3F17-40C4-8C7B-0F5AACEF62C5}.Debug|Win32.ActiveCfg = Debug|Win32 + {D417C165-3F17-40C4-8C7B-0F5AACEF62C5}.Debug|Win32.Build.0 = Debug|Win32 + {D417C165-3F17-40C4-8C7B-0F5AACEF62C5}.Debug|x64.ActiveCfg = Debug|x64 + {D417C165-3F17-40C4-8C7B-0F5AACEF62C5}.Debug|x64.Build.0 = Debug|x64 + {D417C165-3F17-40C4-8C7B-0F5AACEF62C5}.Debug|x86.ActiveCfg = Debug|Win32 + {D417C165-3F17-40C4-8C7B-0F5AACEF62C5}.Debug|x86.Build.0 = Debug|Win32 + {D417C165-3F17-40C4-8C7B-0F5AACEF62C5}.Release|Any CPU.ActiveCfg = Release|Win32 + {D417C165-3F17-40C4-8C7B-0F5AACEF62C5}.Release|Any CPU.Build.0 = Release|Win32 + {D417C165-3F17-40C4-8C7B-0F5AACEF62C5}.Release|ARM.ActiveCfg = Release|ARM + {D417C165-3F17-40C4-8C7B-0F5AACEF62C5}.Release|ARM.Build.0 = Release|ARM + {D417C165-3F17-40C4-8C7B-0F5AACEF62C5}.Release|Win32.ActiveCfg = Release|Win32 + {D417C165-3F17-40C4-8C7B-0F5AACEF62C5}.Release|Win32.Build.0 = Release|Win32 + {D417C165-3F17-40C4-8C7B-0F5AACEF62C5}.Release|x64.ActiveCfg = Release|x64 + {D417C165-3F17-40C4-8C7B-0F5AACEF62C5}.Release|x64.Build.0 = Release|x64 + {D417C165-3F17-40C4-8C7B-0F5AACEF62C5}.Release|x86.ActiveCfg = Release|Win32 + {D417C165-3F17-40C4-8C7B-0F5AACEF62C5}.Release|x86.Build.0 = Release|Win32 + {285130BC-CBF1-4C7A-A28D-6F5EE6C68384}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {285130BC-CBF1-4C7A-A28D-6F5EE6C68384}.Debug|Any CPU.Build.0 = Debug|Win32 + {285130BC-CBF1-4C7A-A28D-6F5EE6C68384}.Debug|ARM.ActiveCfg = Debug|ARM + {285130BC-CBF1-4C7A-A28D-6F5EE6C68384}.Debug|ARM.Build.0 = Debug|ARM + {285130BC-CBF1-4C7A-A28D-6F5EE6C68384}.Debug|Win32.ActiveCfg = Debug|Win32 + {285130BC-CBF1-4C7A-A28D-6F5EE6C68384}.Debug|Win32.Build.0 = Debug|Win32 + {285130BC-CBF1-4C7A-A28D-6F5EE6C68384}.Debug|x64.ActiveCfg = Debug|x64 + {285130BC-CBF1-4C7A-A28D-6F5EE6C68384}.Debug|x64.Build.0 = Debug|x64 + {285130BC-CBF1-4C7A-A28D-6F5EE6C68384}.Debug|x86.ActiveCfg = Debug|Win32 + {285130BC-CBF1-4C7A-A28D-6F5EE6C68384}.Debug|x86.Build.0 = Debug|Win32 + {285130BC-CBF1-4C7A-A28D-6F5EE6C68384}.Release|Any CPU.ActiveCfg = Release|Win32 + {285130BC-CBF1-4C7A-A28D-6F5EE6C68384}.Release|Any CPU.Build.0 = Release|Win32 + {285130BC-CBF1-4C7A-A28D-6F5EE6C68384}.Release|ARM.ActiveCfg = Release|ARM + {285130BC-CBF1-4C7A-A28D-6F5EE6C68384}.Release|ARM.Build.0 = Release|ARM + {285130BC-CBF1-4C7A-A28D-6F5EE6C68384}.Release|Win32.ActiveCfg = Release|Win32 + {285130BC-CBF1-4C7A-A28D-6F5EE6C68384}.Release|Win32.Build.0 = Release|Win32 + {285130BC-CBF1-4C7A-A28D-6F5EE6C68384}.Release|x64.ActiveCfg = Release|x64 + {285130BC-CBF1-4C7A-A28D-6F5EE6C68384}.Release|x64.Build.0 = Release|x64 + {285130BC-CBF1-4C7A-A28D-6F5EE6C68384}.Release|x86.ActiveCfg = Release|Win32 + {285130BC-CBF1-4C7A-A28D-6F5EE6C68384}.Release|x86.Build.0 = Release|Win32 + {59131AB7-2A7D-9A09-8223-174C3F5E0F57}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {59131AB7-2A7D-9A09-8223-174C3F5E0F57}.Debug|Any CPU.Build.0 = Debug|Win32 + {59131AB7-2A7D-9A09-8223-174C3F5E0F57}.Debug|ARM.ActiveCfg = Debug|ARM + {59131AB7-2A7D-9A09-8223-174C3F5E0F57}.Debug|ARM.Build.0 = Debug|ARM + {59131AB7-2A7D-9A09-8223-174C3F5E0F57}.Debug|Win32.ActiveCfg = Debug|Win32 + {59131AB7-2A7D-9A09-8223-174C3F5E0F57}.Debug|Win32.Build.0 = Debug|Win32 + {59131AB7-2A7D-9A09-8223-174C3F5E0F57}.Debug|x64.ActiveCfg = Debug|Win32 + {59131AB7-2A7D-9A09-8223-174C3F5E0F57}.Debug|x86.ActiveCfg = Debug|Win32 + {59131AB7-2A7D-9A09-8223-174C3F5E0F57}.Debug|x86.Build.0 = Debug|Win32 + {59131AB7-2A7D-9A09-8223-174C3F5E0F57}.Release|Any CPU.ActiveCfg = Release|Win32 + {59131AB7-2A7D-9A09-8223-174C3F5E0F57}.Release|Any CPU.Build.0 = Release|Win32 + {59131AB7-2A7D-9A09-8223-174C3F5E0F57}.Release|ARM.ActiveCfg = Release|ARM + {59131AB7-2A7D-9A09-8223-174C3F5E0F57}.Release|ARM.Build.0 = Release|ARM + {59131AB7-2A7D-9A09-8223-174C3F5E0F57}.Release|Win32.ActiveCfg = Release|Win32 + {59131AB7-2A7D-9A09-8223-174C3F5E0F57}.Release|Win32.Build.0 = Release|Win32 + {59131AB7-2A7D-9A09-8223-174C3F5E0F57}.Release|x64.ActiveCfg = Release|Win32 + {59131AB7-2A7D-9A09-8223-174C3F5E0F57}.Release|x64.Build.0 = Release|Win32 + {59131AB7-2A7D-9A09-8223-174C3F5E0F57}.Release|x86.ActiveCfg = Release|Win32 + {59131AB7-2A7D-9A09-8223-174C3F5E0F57}.Release|x86.Build.0 = Release|Win32 + {911EDC63-DB20-4D61-9420-583A1C35427F}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {911EDC63-DB20-4D61-9420-583A1C35427F}.Debug|Any CPU.Build.0 = Debug|Win32 + {911EDC63-DB20-4D61-9420-583A1C35427F}.Debug|ARM.ActiveCfg = Debug|ARM + {911EDC63-DB20-4D61-9420-583A1C35427F}.Debug|ARM.Build.0 = Debug|ARM + {911EDC63-DB20-4D61-9420-583A1C35427F}.Debug|Win32.ActiveCfg = Debug|Win32 + {911EDC63-DB20-4D61-9420-583A1C35427F}.Debug|Win32.Build.0 = Debug|Win32 + {911EDC63-DB20-4D61-9420-583A1C35427F}.Debug|x64.ActiveCfg = Debug|x64 + {911EDC63-DB20-4D61-9420-583A1C35427F}.Debug|x64.Build.0 = Debug|x64 + {911EDC63-DB20-4D61-9420-583A1C35427F}.Debug|x86.ActiveCfg = Debug|Win32 + {911EDC63-DB20-4D61-9420-583A1C35427F}.Debug|x86.Build.0 = Debug|Win32 + {911EDC63-DB20-4D61-9420-583A1C35427F}.Release|Any CPU.ActiveCfg = Release|Win32 + {911EDC63-DB20-4D61-9420-583A1C35427F}.Release|Any CPU.Build.0 = Release|Win32 + {911EDC63-DB20-4D61-9420-583A1C35427F}.Release|ARM.ActiveCfg = Release|ARM + {911EDC63-DB20-4D61-9420-583A1C35427F}.Release|ARM.Build.0 = Release|ARM + {911EDC63-DB20-4D61-9420-583A1C35427F}.Release|Win32.ActiveCfg = Release|Win32 + {911EDC63-DB20-4D61-9420-583A1C35427F}.Release|Win32.Build.0 = Release|Win32 + {911EDC63-DB20-4D61-9420-583A1C35427F}.Release|x64.ActiveCfg = Release|x64 + {911EDC63-DB20-4D61-9420-583A1C35427F}.Release|x64.Build.0 = Release|x64 + {911EDC63-DB20-4D61-9420-583A1C35427F}.Release|x86.ActiveCfg = Release|Win32 + {911EDC63-DB20-4D61-9420-583A1C35427F}.Release|x86.Build.0 = Release|Win32 + {E10C6272-B876-4DC6-9E13-7CA646863B50}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {E10C6272-B876-4DC6-9E13-7CA646863B50}.Debug|Any CPU.Build.0 = Debug|Win32 + {E10C6272-B876-4DC6-9E13-7CA646863B50}.Debug|ARM.ActiveCfg = Debug|ARM + {E10C6272-B876-4DC6-9E13-7CA646863B50}.Debug|ARM.Build.0 = Debug|ARM + {E10C6272-B876-4DC6-9E13-7CA646863B50}.Debug|Win32.ActiveCfg = Debug|Win32 + {E10C6272-B876-4DC6-9E13-7CA646863B50}.Debug|Win32.Build.0 = Debug|Win32 + {E10C6272-B876-4DC6-9E13-7CA646863B50}.Debug|x64.ActiveCfg = Debug|Win32 + {E10C6272-B876-4DC6-9E13-7CA646863B50}.Debug|x86.ActiveCfg = Debug|Win32 + {E10C6272-B876-4DC6-9E13-7CA646863B50}.Debug|x86.Build.0 = Debug|Win32 + {E10C6272-B876-4DC6-9E13-7CA646863B50}.Release|Any CPU.ActiveCfg = Release|Win32 + {E10C6272-B876-4DC6-9E13-7CA646863B50}.Release|Any CPU.Build.0 = Release|Win32 + {E10C6272-B876-4DC6-9E13-7CA646863B50}.Release|ARM.ActiveCfg = Release|ARM + {E10C6272-B876-4DC6-9E13-7CA646863B50}.Release|ARM.Build.0 = Release|ARM + {E10C6272-B876-4DC6-9E13-7CA646863B50}.Release|Win32.ActiveCfg = Release|Win32 + {E10C6272-B876-4DC6-9E13-7CA646863B50}.Release|Win32.Build.0 = Release|Win32 + {E10C6272-B876-4DC6-9E13-7CA646863B50}.Release|x64.ActiveCfg = Release|Win32 + {E10C6272-B876-4DC6-9E13-7CA646863B50}.Release|x64.Build.0 = Release|Win32 + {E10C6272-B876-4DC6-9E13-7CA646863B50}.Release|x86.ActiveCfg = Release|Win32 + {E10C6272-B876-4DC6-9E13-7CA646863B50}.Release|x86.Build.0 = Release|Win32 + {B897969C-6EA9-4DFC-B7E0-94F1C6D94856}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {B897969C-6EA9-4DFC-B7E0-94F1C6D94856}.Debug|Any CPU.Build.0 = Debug|Win32 + {B897969C-6EA9-4DFC-B7E0-94F1C6D94856}.Debug|ARM.ActiveCfg = Debug|ARM + {B897969C-6EA9-4DFC-B7E0-94F1C6D94856}.Debug|ARM.Build.0 = Debug|ARM + {B897969C-6EA9-4DFC-B7E0-94F1C6D94856}.Debug|Win32.ActiveCfg = Debug|Win32 + {B897969C-6EA9-4DFC-B7E0-94F1C6D94856}.Debug|Win32.Build.0 = Debug|Win32 + {B897969C-6EA9-4DFC-B7E0-94F1C6D94856}.Debug|x64.ActiveCfg = Debug|x64 + {B897969C-6EA9-4DFC-B7E0-94F1C6D94856}.Debug|x64.Build.0 = Debug|x64 + {B897969C-6EA9-4DFC-B7E0-94F1C6D94856}.Debug|x86.ActiveCfg = Debug|Win32 + {B897969C-6EA9-4DFC-B7E0-94F1C6D94856}.Debug|x86.Build.0 = Debug|Win32 + {B897969C-6EA9-4DFC-B7E0-94F1C6D94856}.Release|Any CPU.ActiveCfg = Release|Win32 + {B897969C-6EA9-4DFC-B7E0-94F1C6D94856}.Release|Any CPU.Build.0 = Release|Win32 + {B897969C-6EA9-4DFC-B7E0-94F1C6D94856}.Release|ARM.ActiveCfg = Release|ARM + {B897969C-6EA9-4DFC-B7E0-94F1C6D94856}.Release|ARM.Build.0 = Release|ARM + {B897969C-6EA9-4DFC-B7E0-94F1C6D94856}.Release|Win32.ActiveCfg = Release|Win32 + {B897969C-6EA9-4DFC-B7E0-94F1C6D94856}.Release|Win32.Build.0 = Release|Win32 + {B897969C-6EA9-4DFC-B7E0-94F1C6D94856}.Release|x64.ActiveCfg = Release|x64 + {B897969C-6EA9-4DFC-B7E0-94F1C6D94856}.Release|x64.Build.0 = Release|x64 + {B897969C-6EA9-4DFC-B7E0-94F1C6D94856}.Release|x86.ActiveCfg = Release|Win32 + {B897969C-6EA9-4DFC-B7E0-94F1C6D94856}.Release|x86.Build.0 = Release|Win32 + {22702832-C3FD-48E5-BC7D-3879CA50A2ED}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {22702832-C3FD-48E5-BC7D-3879CA50A2ED}.Debug|Any CPU.Build.0 = Debug|Win32 + {22702832-C3FD-48E5-BC7D-3879CA50A2ED}.Debug|ARM.ActiveCfg = Debug|ARM + {22702832-C3FD-48E5-BC7D-3879CA50A2ED}.Debug|ARM.Build.0 = Debug|ARM + {22702832-C3FD-48E5-BC7D-3879CA50A2ED}.Debug|Win32.ActiveCfg = Debug|Win32 + {22702832-C3FD-48E5-BC7D-3879CA50A2ED}.Debug|Win32.Build.0 = Debug|Win32 + {22702832-C3FD-48E5-BC7D-3879CA50A2ED}.Debug|x64.ActiveCfg = Debug|x64 + {22702832-C3FD-48E5-BC7D-3879CA50A2ED}.Debug|x64.Build.0 = Debug|x64 + {22702832-C3FD-48E5-BC7D-3879CA50A2ED}.Debug|x86.ActiveCfg = Debug|Win32 + {22702832-C3FD-48E5-BC7D-3879CA50A2ED}.Debug|x86.Build.0 = Debug|Win32 + {22702832-C3FD-48E5-BC7D-3879CA50A2ED}.Release|Any CPU.ActiveCfg = Release|Win32 + {22702832-C3FD-48E5-BC7D-3879CA50A2ED}.Release|Any CPU.Build.0 = Release|Win32 + {22702832-C3FD-48E5-BC7D-3879CA50A2ED}.Release|ARM.ActiveCfg = Release|ARM + {22702832-C3FD-48E5-BC7D-3879CA50A2ED}.Release|ARM.Build.0 = Release|ARM + {22702832-C3FD-48E5-BC7D-3879CA50A2ED}.Release|Win32.ActiveCfg = Release|Win32 + {22702832-C3FD-48E5-BC7D-3879CA50A2ED}.Release|Win32.Build.0 = Release|Win32 + {22702832-C3FD-48E5-BC7D-3879CA50A2ED}.Release|x64.ActiveCfg = Release|x64 + {22702832-C3FD-48E5-BC7D-3879CA50A2ED}.Release|x64.Build.0 = Release|x64 + {22702832-C3FD-48E5-BC7D-3879CA50A2ED}.Release|x86.ActiveCfg = Release|Win32 + {22702832-C3FD-48E5-BC7D-3879CA50A2ED}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/AppInstaller/AppInstaller.rc b/AppInstaller/AppInstaller.rc new file mode 100644 index 0000000..46fe03a --- /dev/null +++ b/AppInstaller/AppInstaller.rc @@ -0,0 +1,529 @@ +// Microsoft Visual C++ generated resource script. +// +#include +#include "resource.h" +///////////////////////////////////////////////////////////////////////////// +// (壬й) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS) +LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED +#pragma code_page(936) + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_MAINICON ICON "res/Icons/Main.ico" + +ICON_TASKBAR ICON "res/Icons/Main.ico" + +ICON_FILE ICON "res/Icons/FileIcon.ico" + +ICON_WHITE ICON "res/Icons/IconWhite.ico" + +ICON_COLOR ICON "res/Icons/IconColor.ico" + + +///////////////////////////////////////////////////////////////////////////// +// +// IMAGE +// + +BLANK_NORMAL IMAGE "res/Button/Normal/blank.png" + +BLANK_LIGHT IMAGE "res/Button/Normal/blank_light.png" + +BLANK_PRESS IMAGE "res/Button/Normal/blank_press.png" + +MIN_NORMAL IMAGE "res/Button/Normal/min_back.png" + +MIN_LIGHT IMAGE "res/Button/Normal/min_light.png" + +MIN_PRESS IMAGE "res/Button/Normal/min_press.png" + +MAX_NORMAL IMAGE "res/Button/Normal/max_back.png" + +MAX_LIGHT IMAGE "res/Button/Normal/max_light.png" + +MAX_PRESS IMAGE "res/Button/Normal/max_press.png" + +RESTORE_NORMAL IMAGE "res/Button/Normal/restore_back.png" + +RESTORE_LIGHT IMAGE "res/Button/Normal/restore_light.png" + +RESTORE_PRESS IMAGE "res/Button/Normal/restore_press.png" + +CANCEL_NORMAL IMAGE "res/Button/Normal/cancel_back.png" + +CANCEL_LIGHT IMAGE "res/Button/Normal/cancel_light.png" + +CANCEL_PRESS IMAGE "res/Button/Normal/cancel_press.png" + +BLANK_LARGR_NORMAL IMAGE "res/Button/Large/blank.png" + +BLANK_LARGR_LIGHT IMAGE "res/Button/Large/blank_light.png" + +BLANK_LARGR_PRESS IMAGE "res/Button/Large/blank_press.png" + +MIN_LARGR_NORMAL IMAGE "res/Button/Large/min_normal.png" + +MIN_LARGE_LIGHT IMAGE "res/Button/Large/min_light.png" + +MIN_LARGR_PRESS IMAGE "res/Button/Large/min_press.png" + +MAX_LARGE_NORMAL IMAGE "res/Button/Large/max_normal.png" + +MAX_LARGE_LIGHT IMAGE "res/Button/Large/max_light.png" + +MAX_LARGE_PRESS IMAGE "res/Button/Large/max_press.png" + +RESTORE_LARGE_NORMAL IMAGE "res/Button/Large/restore_normal.png" + +RESTORE_LARGE_LIGHT IMAGE "res/Button/Large/restore_light.png" + +RESTORE_LARGE_PRESS IMAGE "res/Button/Large/restore_press.png" + +CANCEL_LARGE_NORMAL IMAGE "res/Button/Large/cancel_window_normal.png" + +CANCEL_LARGE_LIGHT IMAGE "res/Button/Large/cancel_window_light.png" + +CANCEL_LARGE_PRESS IMAGE "res/Button/Large/cancel_window_press.png" + + +///////////////////////////////////////////////////////////////////////////// +// +// RCDATA +// + +ICON_METRO RCDATA "res/Icons/IconTitleBar.ico" + + +///////////////////////////////////////////////////////////////////////////// +// +// RT_MANIFEST +// + +IDR_MANIFEST1 RT_MANIFEST "res/manifest.xml" + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +IDR_VERSION_ZH_CN VERSIONINFO + FILEVERSION 1,0,1,7 + PRODUCTVERSION 1,0,1,7 + FILEFLAGSMASK 0x0L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x0L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "080404b0" + BEGIN + VALUE "CompanyName", "Bruce Winter" + VALUE "FileDescription", "Ӧðװ" + VALUE "FileVersion", "1.0.1.7" + VALUE "LegalCopyright", "\\xA9Bruce Winter. All rights reserved." + VALUE "ProductVersion", "1.0.1.7" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x804, 1200 + END +END + +IDR_VERSION_EN_US VERSIONINFO + FILEVERSION 1,0,1,7 + PRODUCTVERSION 1,0,1,7 + FILEFLAGSMASK 0x0L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x0L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e6" + BEGIN + VALUE "CompanyName", "Bruce Winter" + VALUE "FileDescription", "App Installer" + VALUE "FileVersion", "1.0.1.7" + VALUE "LegalCopyright", "\\xA9Bruce Winter. All rights reserved." + VALUE "ProductVersion", "1.0.1.7" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1254 + END +END + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + WIN_TITLE "Ӧðװ" + PAGE_LOADING "Ժ..." + PAGE_1_TITLE "װ %ls" + PAGE_INFO_PUBLISHER ": %ls" +END + +STRINGTABLE +BEGIN + PAGE_INFO_VERSION "汾: %ls" + PAGE_FUNCTIONS ":" + PAGE_CHECK_RUNWHENREADY "׼ʱ" + PAGE_2_LOADCERT "ڵ֤..." + PAGE_2_INSTALL "ڰװ..." + PAGE_3_TITLE "ѡһЧİװԴԼ" + PAGE_4_TITLE "%ls Ѱװ" + PAGE_5_TITLE "%ls װʧ" + DIALOG_SELLET_APPX "Windows Ӧðļ (*.appx, *.appxbundle)" + DIALOG_SELLET_UNI "ļ (*.*)" + BUTTON_1_SER1 "װ" + BUTTON_3_SER1 "ļ" + BUTTON_4_SER1 "" + BUTTON_5_SER1 "ر" + DIALOG_WINTITLE "ѡЧ Windows Ӧðļ" + PAGE_1_APPHASINSTALLED "%ls Ѱװ" +END + +STRINGTABLE +BEGIN + PAGE_2_TITLE "ڰװ %ls" + PAGE_1_APP "Microsoft Store Ӧ" + PAGE_2_LOADING "Ժ..." + PAGE_2_INSTALLING "ڰװ %d%%" + CLHELP_1 "в˵\n\n" + CLHELP_2 "\t/?, /Help\n\tʾ (в˵)\n\n" + CLHELP_3 "\t/DisableFrame\n\tֹʹԻĴڱ߿\n\n" + CLHELP_4 "\t/Win32Window\n\tʹ WebUI Win32 \n\n" + CLHELP_5 "\t/Silent\n\tһ»Զװװɺڼ\n\n" + CLHELP_6 "\t/VerySilent\n\tĬװװʱʾκϢװɺԶ\n\n" +END + +STRINGTABLE +BEGIN + textSupportCPU "ֵ֧Ĵܹ: " + textSupportSystem "ֵ֧ Windows 汾: %ls ߰汾Ӧϵͳ汾: %ls" + textSupportLanguage "ֵ֧: " + textDependency "Ӧ: " + textDependencyItem "%ls, Ͱ汾: %ls" +END + +STRINGTABLE +BEGIN + INITWIDTH "656" + INITHEIGHT "412" + LIMITWIDTH "504" + LIMITHEIGHT "412" +END + +STRINGTABLE +BEGIN + CLHELP_7 "\t/NoGUI\n\tʹ WSAppPkgIns װװʱᵯдڣװɺֶرմ\n\n" +END + +STRINGTABLE +BEGIN + internetClient " Internet " + internetClientServer " Internet Ӳ䵱" + privateNetworkClientServer "ļͥ" + documentsLibrary "ʹĵ" + picturesLibrary "ʹͼƬ" + videosLibrary "ʹƵ" + musicLibrary "ʹֿ" + enterpriseAuthentication "ʹҵƾ" + sharedUserCertificates "ʹ豸ϿõӲ֤" + removableStorage "ʹô洢ⲿ洢豸ϵ" + appointments "ʹе¼" + contacts "ʹϵ" +END + +STRINGTABLE +BEGIN + phoneCall "豸ϵе绰·" + backgroundMediaPlayback "ں̨ý" + pointOfService "ʹɨǺʹſ" + allJoyn "ֲ֧ AllJoyn Ӧú豸" + phoneCallHistoryPublic "绰йʷ¼" + microphone "ʹ˷" + offlineMapsManagement "Ӧóߵͼ" + objects3D "Ա̷ʽ 3D " + graphicsCaptureWithoutBorder "ޱ߿ͼβ" + bluetooth "Ե豸ͨ" + lowLevelDevices "ͼӲ" + location "ʹλ" + humaninterfacedevice "ʹ֧˻ӿ豸 (HID) Э豸" + recordedCallsFolder "ͨ¼" + proximity "ʹֽ֧ͨ (NFC) 豸" + webcam "ʹͷ" +END + +STRINGTABLE +BEGIN + graphicsCaptureProgrammatic "ʹͼβ" + userNotificationListener "Ӧó֪ͨõĵǰ״̬" + userDataTasks "Ӧóõĵǰ״̬" + userAccountInformation "ʻûͼƬ" + usb " USB 豸" + systemManagement "ϵͳ" + spatialPerception "鿴ǰ͹ȥΧ" + smsSend " SMS MMS Ϣ" + blockedChatMessages "ĶʼӦֹ SMS MMS Ϣ" + chat "ĶɾıϢ" + codeGeneration "̬ɴ" + voipCall "ʹ豸 IP (VoIP) " + enterpriseDataPolicy "Ϊ豸ҵض" + inputInjectionBrokered "ӦóԱ̷ʽʽעϵͳ HIDʡ̻ꡣ" + remoteSystem "Ӧóû Microsoft ʻ豸б" +END + +STRINGTABLE +BEGIN + inProcessMediaExtension "ýչ" + webPlatformMediaExtension "Web ƽ̨ýչ" + previewStore "Microsoft Store Ԥ" + confirmAppClose "رԼԼĴڣӳٹرӦó" + runFullTrust "ʹϵͳԴ" + previewUiComposition "Ԥ Windows UI Composition API Խշ" + slapiQueryLicenseValue "ѯ" + localSystemServices "ʹȨеļϰװ" + packageManagement "ֱӹӦ" + packageQuery "ѼйӦõϢ" + packagePolicySystem "밲װ豸ϵӦصϵͳ" + storeAppInstall "Ӧðװ" + appLicensing "Ӧ" + broadFileSystemAccess "ļϵͳ" + allowElevation "ԹԱ" + unvirtualizedResources "джʱעļ" +END + +STRINGTABLE +BEGIN + extendedExecution "Ӧóڽִ̨һʱIJ" + appointmentsSystem "Ӧöȡ޸ûϵ¼" + contactsSystem "ӦöȡָΪ޻еϵϢԼ޸еϵϢ" + phoneCallSystem "Ӧ÷豸ϵе绰" + userDataAccounts "ɷʵʼϵˡȵûʻ" + userDataTasksSystem "ɷϵͳ" +END + +#endif // (壬й) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Ӣ() resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + WIN_TITLE "App Installer" + PAGE_LOADING "Please wait..." + PAGE_1_TITLE "Install %ls?" + PAGE_INFO_PUBLISHER "Publisher: %ls" +END + +STRINGTABLE +BEGIN + PAGE_INFO_VERSION "Version: %ls" + PAGE_FUNCTIONS "Functions:" + PAGE_CHECK_RUNWHENREADY "Launch when ready" + PAGE_2_LOADCERT "Importing certificates..." + PAGE_2_INSTALL "Installing..." + PAGE_3_TITLE "Please select a valid installation source to continue" + PAGE_4_TITLE "%ls is ready" + PAGE_5_TITLE "%ls is failed" + DIALOG_SELLET_APPX "Windows App Package (*.appx, *.appxbundle)" + DIALOG_SELLET_UNI "All files (*.*)" + BUTTON_1_SER1 "Install" + BUTTON_3_SER1 "Open File" + BUTTON_4_SER1 "Launch" + BUTTON_5_SER1 "Cancel" + DIALOG_WINTITLE "Please select a valid app package file" + PAGE_1_APPHASINSTALLED "%ls has been installed" +END + +STRINGTABLE +BEGIN + PAGE_2_TITLE "Installing %s" + PAGE_1_APP "Microsoft Store App" + PAGE_2_LOADING "Please wait..." + PAGE_2_INSTALLING "Installing %d%%" + CLHELP_1 "Usage:\n\n" + CLHELP_2 "\t/?, /Help\n\tDisplay help window (command line parameter description).\n\n" + CLHELP_3 "\t/DisableFrame\n\tDisable the use of self-drawn window borders.\n\n" + CLHELP_4 "\t/Win32Window\n\tDo not use WebUI, use Win32 window instead.\n\n" + CLHELP_5 "\t/Silent\n\tUnder normal circumstances, it will be automatically installed and will end after a few seconds.\n\n" + CLHELP_6 "\t/VerySilent\n\tSilent installation, no information will be displayed during installation, and the installation task will automatically end after completion.\n\n" +END + +STRINGTABLE +BEGIN + textSupportCPU "Supported processor architectures: " + textSupportSystem "Supported Windows versions: %ls and later (minimum running system version of the app: %ls)" + textSupportLanguage "Supported languages:" + textDependency "The following are the dependencies required by the application:" + textDependencyItem "%ls, minimum required version: %ls" +END + +STRINGTABLE +BEGIN + CLHELP_7 "\t/NoGUI\n\tUse WSAppPkgIns to install. A command line window will pop up during installation, and you need to manually close the window after installation.\n\n" +END + +STRINGTABLE +BEGIN + internetClient "Access your Internet connection" + internetClientServer "Access your Internet connection and act as a server." + privateNetworkClientServer "Access your home or work networks" + documentsLibrary "Use your documents library" + picturesLibrary "Use your pictures library" + videosLibrary "Use your video library" + musicLibrary "Use your music library" + enterpriseAuthentication "Use your enterprise domain credentials" + sharedUserCertificates "Use the software and hardware certificates available on your device" + removableStorage "Use data stored on an external storage device" + appointments "Use the appointments in your calendar" + contacts "Use your contacts" +END + +STRINGTABLE +BEGIN + phoneCall "Access all the phone lines on your device" + backgroundMediaPlayback "Play media in the background" + pointOfService "Use barcode scanners and magnetic card readers" + allJoyn "Discover and interact with AllJoyn enabled apps and devices" + phoneCallHistoryPublic "Phone Calls Public History" + microphone "Use your microphone" + offlineMapsManagement "Allows the application to access offline maps." + objects3D "Programmatically access your 3D Objects" + graphicsCaptureWithoutBorder "Allows borderless graphics capture" + bluetooth "Communicate with already paired Bluetooth devices" + lowLevelDevices "IoT Low-Level Bus Hardware" + location "Use your location" + humaninterfacedevice "Use your devices that support the Human Interface Device (HID) protocol" + recordedCallsFolder "Access your recorded calls" + proximity "Use devices that support Near Field Communication (NFC) services" + webcam "Use your webcam" +END + +STRINGTABLE +BEGIN + graphicsCaptureProgrammatic "Allows use of graphics capture" + userNotificationListener + "Allows an application to access the current state of notification settings" + userDataTasks "Allows an application to access the current state of task settings" + userAccountInformation "Access to your Account's username and picture" + usb "Access your USB connected devices" + systemManagement "IoT System Adminstration" + spatialPerception "See your current and past surroundings" + smsSend "Send SMS and MMS messages" + blockedChatMessages "Read SMS and MMS messages that have been blocked by the Spam Filter app" + chat "Read and delete Text Messages" + codeGeneration "Generate code dynamically" + voipCall "Use your device's voice over IP (VoIP) services" + enterpriseDataPolicy "Define enterprise-specific policies for your device" + inputInjectionBrokered "Allows an application to programmatically inject various forms of input into the system, such as HID, touch, pen, keyboard, or mouse." + remoteSystem "Allows the application to access the list of devices associated with the user's Microsoft account" +END + +STRINGTABLE +BEGIN + inProcessMediaExtension "In-process Media Extension" + webPlatformMediaExtension "Web Platform Media Extension" + previewStore "Microsoft Store Preview Features" + confirmAppClose "Close themselves and their own windows, and delay the closing of their app" + runFullTrust "Uses all system resources" + previewUiComposition "Preview the Windows UI Composition API to receive feedback" + slapiQueryLicenseValue "Query software licensing policies" + localSystemServices "Install a service on the machine that runs with maximum privileges" + packageManagement "Manage other apps directly" + packageQuery "Gather information about other apps" + packagePolicySystem "Control system policies related to apps that are installed on the device" + storeAppInstall "Store app installation" + appLicensing "App Licensing" + broadFileSystemAccess "File System" + allowElevation "Run as administrator" + unvirtualizedResources "Write registry entries and files that are not cleaned up on uninstall" +END + +STRINGTABLE +BEGIN + extendedExecution "Allows the app to continue to perform operations for a period of time after entering the background" + appointmentsSystem "Allows the app to read and modify all appointments on the user's calendar" + contactsSystem "Allows the app to read information about contacts that have been designated as restricted or sensitive, and to modify existing contact information." + phoneCallSystem "Allows the app to access all phone lines on the device" + userDataAccounts "Allows the program to access user data such as email, contacts, calendar, etc." + userDataTasksSystem "Access to system tasks" +END + +#endif // Ӣ() resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/AppInstaller/AppInstaller.vcxproj b/AppInstaller/AppInstaller.vcxproj new file mode 100644 index 0000000..90b29e4 --- /dev/null +++ b/AppInstaller/AppInstaller.vcxproj @@ -0,0 +1,333 @@ + + + + + Debug + ARM + + + Debug + Win32 + + + Release + ARM + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {D417C165-3F17-40C4-8C7B-0F5AACEF62C5} + Win32Proj + AppInstaller + + + + Application + true + v140 + Unicode + true + false + + + Application + true + v140 + Unicode + true + false + + + Application + false + v140 + true + Unicode + true + + + Application + false + v140 + true + Unicode + true + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + + + true + ($SolutionDir)\AppLauncher;($SolutionDir)\PackageManagerAdd;E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstaller\AppLauncher;E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstaller\PackageManagerAdd;($SolutionDir)\Base64Img;E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstaller\Base64Img;E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstaller\ToastNotification;E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstaller\PriReader2;E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstaller\CertificateManager;$(IncludePath) + + + true + ($SolutionDir)\AppLauncher;($SolutionDir)\PackageManagerAdd;E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstaller\AppLauncher;E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstaller\PackageManagerAdd;($SolutionDir)\Base64Img;E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstaller\Base64Img;E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstaller\ToastNotification;E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstaller\PriReader2;E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstaller\CertificateManager;$(IncludePath) + + + true + + + false + ($SolutionDir)\AppLauncher;($SolutionDir)\PackageManagerAdd;E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstaller\AppLauncher;E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstaller\PackageManagerAdd;($SolutionDir)\Base64Img;E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstaller\Base64Img;E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstaller\ToastNotification;E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstaller\PriReader2;E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstaller\CertificateManager;$(IncludePath) + + + false + ($SolutionDir)\AppLauncher;($SolutionDir)\PackageManagerAdd;E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstaller\AppLauncher;E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstaller\PackageManagerAdd;($SolutionDir)\Base64Img;E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstaller\Base64Img;E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstaller\ToastNotification;E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstaller\PriReader2;E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstaller\CertificateManager;$(IncludePath) + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + + + Windows + true + shlwapi.lib;dwmapi.lib;crypt32.lib;$(OutDir)PackageManager.lib;$(OutDir)AppLauncher.lib;$(OutDir)Base64Img.lib;$(OutDir)ToastNotification.lib;$(OutDir)PriReader2.lib;$(OutDir)CertificateManager.lib + RequireAdministrator + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + + + Windows + true + shlwapi.lib;dwmapi.lib;crypt32.lib;$(OutDir)PackageManager.lib;$(OutDir)AppLauncher.lib;$(OutDir)Base64Img.lib;$(OutDir)ToastNotification.lib;$(OutDir)PriReader2.lib;$(OutDir)CertificateManager.lib + + + + + + + Level3 + Disabled + _DEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + + + Windows + true + + + + + Level3 + + + Full + true + false + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + MultiThreadedDLL + false + + + Windows + true + true + true + shlwapi.lib;dwmapi.lib;crypt32.lib;$(OutDir)PackageManager.lib;$(OutDir)AppLauncher.lib;$(OutDir)Base64Img.lib;$(OutDir)ToastNotification.lib;$(OutDir)PriReader2.lib;$(OutDir)CertificateManager.lib + RequireAdministrator + + + false + + + + + Level3 + + + Full + true + true + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + shlwapi.lib;dwmapi.lib;crypt32.lib;$(OutDir)PackageManager.lib;$(OutDir)AppLauncher.lib;$(OutDir)Base64Img.lib;$(OutDir)ToastNotification.lib;$(OutDir)PriReader2.lib;$(OutDir)CertificateManager.lib + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Drawing.dll + + + C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Drawing.Design.dll + + + C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Windows.Forms.dll + + + + C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\System.Xml.Linq.dll + + + + + {285130bc-cbf1-4c7a-a28d-6f5ee6c68384} + + + {911edc63-db20-4d61-9420-583a1c35427f} + + + {22702832-c3fd-48e5-bc7d-3879ca50a2ed} + + + {59131ab7-2a7d-9a09-8223-174c3f5e0f57} + + + {b897969c-6ea9-4dfc-b7e0-94f1c6d94856} + + + {e10c6272-b876-4dc6-9e13-7ca646863b50} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/AppInstaller/AppInstaller.vcxproj.filters b/AppInstaller/AppInstaller.vcxproj.filters new file mode 100644 index 0000000..e075e93 --- /dev/null +++ b/AppInstaller/AppInstaller.vcxproj.filters @@ -0,0 +1,178 @@ + + + + + {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/AppInstaller/base64logo.h b/AppInstaller/base64logo.h new file mode 100644 index 0000000..7457968 --- /dev/null +++ b/AppInstaller/base64logo.h @@ -0,0 +1,291 @@ +#pragma once +#include "Base64Img.h" +#include +#include +#include +#include "pkgcode.h" +#include "priread.h" + +std::string GetFileNameWithoutExtension (LPCSTR filePath) +{ + char pathCopy [MAX_PATH]; + lstrcpynA (pathCopy, filePath, MAX_PATH); + char *fileName = PathFindFileNameA (pathCopy); + PathRemoveExtensionA (fileName); + return std::string (fileName); +} +std::wstring GetFileNameWithoutExtension (LPCWSTR filePath) +{ + wchar_t pathCopy [MAX_PATH]; + lstrcpynW (pathCopy, filePath, MAX_PATH); + wchar_t *fileName = PathFindFileNameW (pathCopy); + PathRemoveExtensionW (fileName); + return std::wstring (fileName); +} +std::string GetFileNameWithoutExtension (const std::string &filePath) +{ + return GetFileNameWithoutExtension (filePath.c_str ()); +} +std::wstring GetFileNameWithoutExtension (const std::wstring &filePath) +{ + return GetFileNameWithoutExtension (filePath.c_str ()); +} + +std::string GetLogoBase64FromReader (PackageReader &reader, IStream **getOutput = NULL) +{ + if (!&reader) return std::string (""); + if (!reader.isAvailable ()) return std::string (""); + std::wstring logoPath = reader.getPropertyLogo (); + if (logoPath.empty () || logoPath.length () == 0) return std::string (""); + PriReader pri (reader.getPriFileStream ()); + if (pri.isAvailable ()) + { + std::wstring logoPathFromPri = pri.findFilePathValue (logoPath); + if (!logoPathFromPri.empty () && logoPath.length () > 0) logoPath = logoPathFromPri; + } + IStream *imgfile = reader.extractFileToStream (logoPath); + if (getOutput) *getOutput = imgfile; + if (!imgfile) + { + std::wstring fileName = GetFileNameWithoutExtension (logoPath); + IAppxPackageReader *appxreader = reader.getAppxPackageReader (); + CComPtr fe = NULL; + HRESULT hr = appxreader->GetPayloadFiles (&fe); + if (SUCCEEDED (hr) && fe) + { + std::vector files; + BOOL hasCurrent = FALSE; + hr = fe->GetHasCurrent (FALSE); + while (SUCCEEDED (hr) && hasCurrent) + { + CComPtr ifile = NULL; + hr = fe->GetCurrent (&ifile); + if (SUCCEEDED (hr) && ifile) + { + LPWSTR lpstr = NULL; + if (SUCCEEDED (ifile->GetName (&lpstr)) && lpstr) + { + std::wstring strWillSearch = StringToUpper (StringTrim (lpstr)); + std::wstring strWillToSearch = StringToUpper (StringTrim (fileName)); + if (StrStrW (strWillSearch.c_str (), strWillToSearch.c_str ())) + { + bool isFind = LabelEqual (PathFindExtensionW (lpstr), L".png"); + if (!isFind) isFind = LabelEqual (PathFindExtensionW (lpstr), L".jpg"); + if (!isFind) isFind = LabelEqual (PathFindExtensionW (lpstr), L".jpeg"); + if (!isFind) isFind = LabelEqual (PathFindExtensionW (lpstr), L".bmp"); + if (isFind) + { + std::wstring temp (L""); + if (lpstr) temp += lpstr; + if (temp.length () > 0) push_no_repeat (files, temp); + } + } + } + } + } + bool isFindSuit = false; + { + std::map scaleFiles; + std::wregex pattern (L"(scale-(\\d+))"); + for (auto it : files) + { + if (StrStrW (it.c_str (), L"contrast-")) continue; + std::wsmatch match; + if (std::regex_search (it, match, pattern)) + { + int temp = StrToIntW (match [1].str ().c_str ()); + if (!temp) + { + scaleFiles [temp] = it; + } + } + } + if (scaleFiles.find (GetDPI ()) != scaleFiles.end ()) + { + isFindSuit = true; + logoPath = scaleFiles [GetDPI ()]; + } + else + { + bool isFindScale = false; + for (auto it : scaleFiles) + { + if (it.first >= GetDPI ()) + { + isFindScale = true; + logoPath = scaleFiles [GetDPI ()]; + break; + } + } + if (!isFindScale) + { + for (auto it : scaleFiles) + { + if (it.first >= 100) + { + isFindScale = true; + logoPath = scaleFiles [GetDPI ()]; + break; + } + } + } + if (!isFindScale) + { + for (auto it : scaleFiles) + { + isFindScale = true; + logoPath = scaleFiles [GetDPI ()]; + break; + } + } + isFindSuit = isFindScale; + } + } + if (!isFindSuit) + { + std::map scaleFiles; + std::wregex pattern (L"(scale-(\\d+))"); + for (auto it : files) + { + if (StrStrW (it.c_str (), L"contrast-white")) continue; + std::wsmatch match; + if (std::regex_search (it, match, pattern)) + { + int temp = StrToIntW (match [1].str ().c_str ()); + if (!temp) + { + scaleFiles [temp] = it; + } + } + } + if (scaleFiles.find (GetDPI ()) != scaleFiles.end ()) + { + isFindSuit = true; + logoPath = scaleFiles [GetDPI ()]; + } + else + { + bool isFindScale = false; + for (auto it : scaleFiles) + { + if (it.first >= GetDPI ()) + { + isFindScale = true; + logoPath = scaleFiles [GetDPI ()]; + break; + } + } + if (!isFindScale) + { + for (auto it : scaleFiles) + { + if (it.first >= 100) + { + isFindScale = true; + logoPath = scaleFiles [GetDPI ()]; + break; + } + } + } + if (!isFindScale) + { + for (auto it : scaleFiles) + { + isFindScale = true; + logoPath = scaleFiles [GetDPI ()]; + break; + } + } + isFindSuit = isFindScale; + } + } + if (!isFindSuit) + { + std::map scaleFiles; + std::wregex pattern (L"(scale-(\\d+))"); + for (auto it : files) + { + if (StrStrW (it.c_str (), L"contrast-black")) continue; + std::wsmatch match; + if (std::regex_search (it, match, pattern)) + { + int temp = StrToIntW (match [1].str ().c_str ()); + if (!temp) + { + scaleFiles [temp] = it; + } + } + } + if (scaleFiles.find (GetDPI ()) != scaleFiles.end ()) + { + isFindSuit = true; + logoPath = scaleFiles [GetDPI ()]; + } + else + { + bool isFindScale = false; + for (auto it : scaleFiles) + { + if (it.first >= GetDPI ()) + { + isFindScale = true; + logoPath = scaleFiles [GetDPI ()]; + break; + } + } + if (!isFindScale) + { + for (auto it : scaleFiles) + { + if (it.first >= 100) + { + isFindScale = true; + logoPath = scaleFiles [GetDPI ()]; + break; + } + } + } + if (!isFindScale) + { + for (auto it : scaleFiles) + { + isFindScale = true; + logoPath = scaleFiles [GetDPI ()]; + break; + } + } + isFindSuit = isFindScale; + } + } + if (!isFindSuit) + { + for (auto it : files) + { + logoPath = std::wstring (L"") + it; + break; + } + } + } + imgfile = reader.extractFileToStream (logoPath); + } + if (getOutput) *getOutput = imgfile; + if (!imgfile) return std::string (""); + std::string b64res (""); + LPSTR szRes = StreamToBase64 (imgfile); + if (!getOutput) + { + if (imgfile) + { + imgfile->Release (); + imgfile = NULL; + } + } + if (!szRes) return b64res; + if (szRes) b64res += szRes; + free (szRes); + if (b64res.length () > 0) + { + b64res = "data:image/png;base64," + b64res; + } + return b64res; +} \ No newline at end of file diff --git a/AppInstaller/initread.h b/AppInstaller/initread.h new file mode 100644 index 0000000..da43915 --- /dev/null +++ b/AppInstaller/initread.h @@ -0,0 +1,194 @@ +#pragma once +#include +#include +#include +#include +#include "pkgcode.h" + +unsigned _wtou (const wchar_t *str) +{ + unsigned value = 0; + if (str) + { + swscanf (str, L"%u", &value); + } + return value; +} +unsigned long _wtoul (const wchar_t *str) +{ + unsigned value = 0; + if (str) + { + swscanf (str, L"%'u", &value); + } + return value; +} +unsigned long long _wtou64 (const wchar_t *str) +{ + unsigned long long value = 0; + if (str) + { + swscanf (str, L"%llu", &value); + } + return value; +} +double _wtod (const wchar_t *str) +{ + if (!str || !*str) return 0.0; // ַָ + double value = 0.0; + if (swscanf (str, L"%lg", &value) == 1) + { + return value; + } + return 0.0; // ʧʱ 0.0 +} + +std::string GetPrivateProfileStringA (std::string filePath, std::string section, std::string key, LPCSTR defaultValue = "") +{ + char buf [32768] = {0}; + GetPrivateProfileStringA (section.c_str (), key.c_str (), defaultValue, buf, 32767, filePath.c_str ()); + return buf; +} +std::wstring GetPrivateProfileStringW (std::wstring filePath, std::wstring section, std::wstring key, LPCWSTR defaultValue = L"") +{ + WCHAR buf [32768] = {0}; + GetPrivateProfileStringW (section.c_str (), key.c_str (), defaultValue, buf, 32767, filePath.c_str ()); + return buf; +} +UINT GetPrivateProfileIntA (std::string filePath, std::string section, std::string key, INT defaultValue = 0) +{ + return GetPrivateProfileIntA (section.c_str (), key.c_str (), defaultValue, filePath.c_str ()); +} +UINT GetPrivateProfileIntW (std::wstring filePath, std::wstring section, std::wstring key, INT defaultValue = 0) +{ + return GetPrivateProfileIntW (section.c_str (), key.c_str (), defaultValue, filePath.c_str ()); +} + +class WInitFile +{ + private: + std::wstring m_filePath; + template std::wstring numberToString (t src, std::wstring format) + { + WCHAR buf [256] = {0}; + swprintf (buf, format.c_str (), src); + return buf; + } + public: + WInitFile (LPCWSTR lpswFilePath = L""): m_filePath (lpswFilePath) {} + void setFilePath (std::wstring filePath) + { + this->m_filePath = L""; + this->m_filePath += filePath; + } + std::wstring getFilePath () const { return this->m_filePath; } + std::wstring readStringValue (std::wstring section, std::wstring key, std::wstring defaultValue = L"") + { + return GetPrivateProfileStringW (this->m_filePath, section, key, defaultValue.c_str ()); + } + bool readBoolValue (std::wstring section, std::wstring key, bool defaultValue = false) + { + std::wstring res = this->readStringValue (section, key, (defaultValue ? L"true" : L"false")); + if (LabelEqual (res, L"true") || LabelEqual (res, L"zhen") || LabelEqual (res, L"1") || LabelEqual (res, L"yes") || LabelEqual (res, L"")) + { + return true; + } + else if (LabelEqual (res, L"false") || LabelEqual (res, L"jia") || LabelEqual (res, L"0") || LabelEqual (res, L"no") || LabelEqual (res, L"")) + { + return false; + } + return false; + } + int readIntValue (std::wstring section, std::wstring key, int defaultValue = 0) + { + WCHAR buf [256] = {0}; + swprintf (buf, L"%d", defaultValue); + return _wtoi (this->readStringValue (section, key, buf).c_str ()); + } + unsigned readUIntValue (std::wstring section, std::wstring key, unsigned defaultValue = 0) + { + WCHAR buf [256] = {0}; + swprintf (buf, L"%u", defaultValue); + return _wtou (this->readStringValue (section, key, buf).c_str ()); + } + long readLongValue (std::wstring section, std::wstring key, long defaultValue = 0) + { + WCHAR buf [256] = {0}; + swprintf (buf, L"%ld", defaultValue); + return _wtol (this->readStringValue (section, key, buf).c_str ()); + } + unsigned long readULongValue (std::wstring section, std::wstring key, unsigned long defaultValue = 0) + { + WCHAR buf [256] = {0}; + swprintf (buf, L"%lu", defaultValue); + return _wtoul (this->readStringValue (section, key, buf).c_str ()); + } + long long readLongLongValue (std::wstring section, std::wstring key, long long defaultValue = 0) + { + WCHAR buf [256] = {0}; + swprintf (buf, L"%lld", defaultValue); + return _wtoll (this->readStringValue (section, key, buf).c_str ()); + } + unsigned long long readULongLongValue (std::wstring section, std::wstring key, unsigned long long defaultValue = 0) + { + WCHAR buf [256] = {0}; + swprintf (buf, L"%llu", defaultValue); + return _wtou64 (this->readStringValue (section, key, buf).c_str ()); + } + float readFloatValue (std::wstring section, std::wstring key, float defaultValue = 0) + { + WCHAR buf [256] = {0}; + swprintf (buf, L"%f", defaultValue); + return _wtof (this->readStringValue (section, key, buf).c_str ()); + } + double readDoubleValue (std::wstring section, std::wstring key, double defaultValue = 0) + { + WCHAR buf [256] = {0}; + swprintf (buf, L"%lf", defaultValue); + return _wtod (this->readStringValue (section, key, buf).c_str ()); + } + bool writeStringValue (std::wstring section, std::wstring key, std::wstring value) + { + return WritePrivateProfileStringW (section.c_str (), key.c_str (), value.c_str (), this->m_filePath.c_str ()); + } + bool writeBoolValue (std::wstring section, std::wstring key, bool value) + { + return this->writeBoolValue (section, key, value ? L"true" : L"false"); + } + bool writeIntValue (std::wstring section, std::wstring key, int value) + { + return this->writeStringValue (section, key, this->numberToString (value, L"%d")); + } + bool writeUIntValue (std::wstring section, std::wstring key, unsigned value) + { + return this->writeStringValue (section, key, this->numberToString (value, L"%u")); + } + bool writeLongValue (std::wstring section, std::wstring key, long value) + { + return this->writeStringValue (section, key, this->numberToString (value, L"%ld")); + } + bool writeULongValue (std::wstring section, std::wstring key, unsigned long value) + { + return this->writeStringValue (section, key, this->numberToString (value, L"%lu")); + } + bool writeLongLongValue (std::wstring section, std::wstring key, long long value) + { + return this->writeStringValue (section, key, this->numberToString (value, L"%lld")); + } + bool writeULongLongValue (std::wstring section, std::wstring key, unsigned long long value) + { + return this->writeStringValue (section, key, this->numberToString (value, L"%llu")); + } + bool writeFloatValue (std::wstring section, std::wstring key, float value) + { + return this->writeStringValue (section, key, this->numberToString (value, L"%g")); + } + bool writeDoublegValue (std::wstring section, std::wstring key, double value) + { + return this->writeStringValue (section, key, this->numberToString (value, L"%g")); + } + bool isAvaliable () + { + return IsFileExists (this->m_filePath); + } +}; \ No newline at end of file diff --git a/AppInstaller/localeex.h b/AppInstaller/localeex.h new file mode 100644 index 0000000..326b816 --- /dev/null +++ b/AppInstaller/localeex.h @@ -0,0 +1,111 @@ +#pragma once +#include +#include +#include +#include + +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; +} + +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; +} +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; +} +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 ()); +} +std::string GetLocaleRestrictedCodeFromLcidA (LCID lcid) +{ + return GetLocaleInfoA (lcid, 89); +} +std::wstring GetLocaleRestrictedCodeFromLcidW (LCID lcid) +{ + return GetLocaleInfoW (lcid, 89); +} +std::string GetLocaleElaboratedCodeFromLcidA (LCID lcid) +{ + return GetLocaleInfoA (lcid, 90); +} +std::wstring GetLocaleElaboratedCodeFromLcidW (LCID lcid) +{ + return GetLocaleInfoW (lcid, 90); +} +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 ()); +} +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::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::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); +} diff --git a/AppInstaller/mainwnd.cpp b/AppInstaller/mainwnd.cpp new file mode 100644 index 0000000..df82696 --- /dev/null +++ b/AppInstaller/mainwnd.cpp @@ -0,0 +1,1464 @@ +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS +#endif +#ifndef _CRT_NON_CONFORMING_SWPRINTFS +#define _CRT_NON_CONFORMING_SWPRINTFS +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pkgcode.h" +#include "resource.h" +#include "res2.h" +#include "PackageManager.h" +#include "base64logo.h" +#include "AppLauncher.h" +#include "ToastNotification.h" +#include "pkginfo.h" +#include "CertificateManager.h" +#include "initread.h" +#include + +using namespace System; +using namespace System::Windows::Forms; +using namespace System::Threading; + +#define toInt(_String_Managed_Object_) Int32::Parse (_String_Managed_Object_) +#define toDouble(_String_Managed_Object_) Double::Parse (_String_Managed_Object_) +#define toBool(_String_Managed_Object_) Boolean::Parse (_String_Managed_Object_) +#define toDateTime(_String_Managed_Object_) DateTime::Parse (_String_Managed_Object_) + +String ^GetRCString_NET (UINT resID) +{ + size_t bufferSize = 256; + wchar_t* buffer = nullptr; + int length = 0; + do + { + delete [] buffer; + buffer = new wchar_t [bufferSize]; + length = LoadStringW (GetModuleHandle (nullptr), resID, buffer, bufferSize); + if ((size_t)length >= bufferSize) + { + bufferSize += 20; + } + } while ((size_t)length >= bufferSize); + String^ result = gcnew String (buffer); + delete [] buffer; + return result; +} +std::wstring GetRCString_cpp (UINT resID) +{ + size_t bufferSize = 256; + wchar_t* buffer = nullptr; + int length = 0; + do + { + delete [] buffer; + buffer = new wchar_t [bufferSize]; + length = LoadStringW (GetModuleHandle (nullptr), resID, buffer, bufferSize); + if ((size_t)length >= bufferSize) + { + bufferSize += 20; + } + } while ((size_t)length >= bufferSize); + std::wstring result = L""; + result += buffer; + delete [] buffer; + return result; +} +#define GetRCString GetRCString_NET +#define GetRCIntValue(_UINT__resID_) toInt (GetRCString (_UINT__resID_)) +#define GetRCDoubleValue(_UINT__resID_) toDouble (GetRCString (_UINT__resID_)) +#define GetRCBoolValue(_UINT__resID_) toBool (GetRCString (_UINT__resID_)) +#define GetRCDateTimeValue(_UINT__resID_) toDateTime (GetRCString (_UINT__resID_)) +#define rcString(resID) GetRCString (resID) +#define rcInt(resID) GetRCIntValue (resID) +#define rcDouble(resID) GetRCDoubleValue (resID) +#define rcBool(resID) GetRCBoolValue (resID) +#define rcDTime(resID) GetRCDateTimeValue (resID) +#define rcIcon(resID) LoadRCIcon (resID) + +HICON LoadRCIcon (UINT resID) +{ + // Դͼ + HICON hIcon = (HICON)LoadImage (GetModuleHandle (nullptr), MAKEINTRESOURCE (resID), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE); + if (hIcon == nullptr) return nullptr; + return hIcon; +} +HRSRC FindResourceByName (LPCWSTR resourceName, LPCWSTR resourceType) +{ + return FindResourceW (GetModuleHandle (nullptr), resourceName, resourceType); +} +HRSRC FindResourceByName (const std::wstring &resourceName, LPCWSTR resourceType) +{ + return FindResourceByName (resourceName.c_str (), resourceType); +} + +System::Drawing::Color GetAeroColor () +{ + DWORD color = 0; + BOOL opaqueBlend = FALSE; + // DwmGetColorizationColor ȡ Aero ɫ + HRESULT hr = DwmGetColorizationColor (&color, &opaqueBlend); + if (SUCCEEDED (hr)) { + BYTE r = (BYTE)((color & 0x00FF0000) >> 16); + BYTE g = (BYTE)((color & 0x0000FF00) >> 8); + BYTE b = (BYTE)(color & 0x000000FF); + return System::Drawing::Color::FromArgb (r, g, b); + } + else { + // ȡʧܣĬɫ + return System::Drawing::Color::FromArgb (0, 120, 215); + } +} +// ɫתΪ HTML ɫֵ (#RRGGBB ʽ) +String ^ColorToHtml (System::Drawing::Color color) +{ + return String::Format ("#{0:X2}{1:X2}{2:X2}", color.R, color.G, color.B); +} +bool IsAppInDarkMode () +{ + HKEY hKey; + DWORD dwValue; + if (RegOpenKeyEx (HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", 0, KEY_READ, &hKey) == ERROR_SUCCESS) + { + DWORD dwSize = sizeof (dwValue); + if (RegQueryValueEx (hKey, L"AppsUseLightTheme", NULL, NULL, (LPBYTE)&dwValue, &dwSize) == ERROR_SUCCESS) + { + RegCloseKey (hKey); + return dwValue == 0; + } + RegCloseKey (hKey); + } + return false; +} + +std::wstring StrPrintFormatW (LPCWSTR format, ...) +{ + va_list args; + va_start (args, format); + size_t sizeBuf = 256; + wchar_t* buffer = (wchar_t*)malloc (sizeBuf * sizeof (wchar_t)); + if (!buffer) + { + va_end (args); + return L""; + } + int written = -1; + while (true) + { + written = vswprintf (buffer, sizeBuf, format, args); + if (written >= 0 && static_cast(written) < sizeBuf) + { + break; + } + sizeBuf += 256; + wchar_t* newBuffer = (wchar_t*)realloc (buffer, sizeBuf * sizeof (wchar_t)); + if (!newBuffer) + { + free (buffer); + va_end (args); + return L""; + } + buffer = newBuffer; + } + va_end (args); + std::wstring result (buffer); + free (buffer); + return result; +} + +void SetWebBrowserEmulation () +{ + // ȡӦóĿִļ + String ^appName = System::IO::Path::GetFileNameWithoutExtension (System::Windows::Forms::Application::ExecutablePath); + const wchar_t *appNameWChar = (const wchar_t *)(void *)System::Runtime::InteropServices::Marshal::StringToHGlobalUni (appName); + BOOL is64Bit = FALSE; + IsWow64Process (GetCurrentProcess (), &is64Bit); + HKEY hKey; + long regOpenResult = ERROR_SUCCESS; + if (is64Bit) + { + regOpenResult = RegOpenKeyExW (HKEY_CURRENT_USER, L"SOFTWARE\\WOW6432Node\\Microsoft\\Internet Explorer\\Main\\FeatureControl\\FEATURE_BROWSER_EMULATION", 0, KEY_WRITE, &hKey); + } + else + { + regOpenResult = RegOpenKeyExW (HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Internet Explorer\\Main\\FeatureControl\\FEATURE_BROWSER_EMULATION", 0, KEY_WRITE, &hKey); + } + if (regOpenResult == ERROR_SUCCESS) + { + DWORD ie11Mode = 11001; + RegSetValueExW (hKey, appNameWChar, 0, REG_DWORD, (const BYTE *)&ie11Mode, sizeof (DWORD)); + RegCloseKey (hKey); + } +} + +#include +#include + +bool IsIeVersion10 () +{ + HKEY hKey; + const wchar_t* ieKeyPath = L"SOFTWARE\\Microsoft\\Internet Explorer"; + const wchar_t* valueName = L"svcVersion"; + DWORD dwType = REG_SZ; + wchar_t version [32]; + DWORD cbData = sizeof (version); + REGSAM samDesired = KEY_READ | KEY_WOW64_64KEY; + if (RegOpenKeyExW (HKEY_LOCAL_MACHINE, ieKeyPath, 0, samDesired, &hKey) != ERROR_SUCCESS) + { + samDesired = KEY_READ | KEY_WOW64_32KEY; + if (RegOpenKeyExW (HKEY_LOCAL_MACHINE, ieKeyPath, 0, samDesired, &hKey) != ERROR_SUCCESS) + { + return false; + } + } + bool isIe10 = false; + if (RegQueryValueExW (hKey, valueName, NULL, &dwType, (LPBYTE)version, &cbData) == ERROR_SUCCESS) + { + std::wstring verStr (version); + size_t dotPos = verStr.find (L'.'); + if (dotPos != std::wstring::npos) + { + int majorVersion = std::stoi (verStr.substr (0, dotPos)); + if (majorVersion == 10) + { + isIe10 = true; + } + } + } + RegCloseKey (hKey); + return isIe10; +} + +size_t EnumerateFilesW (const std::wstring &directory, const std::wstring &filter, + std::vector &outFiles, bool recursive = false) +{ + std::wstring searchPath = directory; + if (!searchPath.empty () && searchPath.back () != L'\\') + { + searchPath += L'\\'; + } + searchPath += filter; + WIN32_FIND_DATAW findData; + HANDLE hFind = FindFirstFileW (searchPath.c_str (), &findData); + if (hFind != INVALID_HANDLE_VALUE) + { + do { + if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + { + outFiles.push_back (directory + L"\\" + findData.cFileName); + } + } while (FindNextFileW (hFind, &findData)); + FindClose (hFind); + } + if (recursive) { + std::wstring subDirSearchPath = directory + L"\\*"; + hFind = FindFirstFileW (subDirSearchPath.c_str (), &findData); + if (hFind != INVALID_HANDLE_VALUE) + { + do { + if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && + wcscmp (findData.cFileName, L".") != 0 && wcscmp (findData.cFileName, L"..") != 0) + { + EnumerateFilesW (directory + L"\\" + findData.cFileName, filter, outFiles, true); + } + } while (FindNextFileW (hFind, &findData)); + FindClose (hFind); + } + } + return outFiles.size (); +} + +std::wstring GetFileDirectoryW (const std::wstring &filePath) +{ + std::wstring directory (L""); + WCHAR *buf = (WCHAR *)calloc (filePath.capacity () + 1, sizeof (WCHAR)); + lstrcpyW (buf, filePath.c_str ()); + PathRemoveFileSpecW (buf); + directory += buf; + free (buf); + return directory; +} + +std::wstring pkgPath = L""; +pkgreader reader; +bool m_silentMode = false; +LPCWSTR m_idenName = L"Microsoft.DesktopAppInstaller"; +PackageInfomation m_pkgInfo; +WInitFile m_initConfig; + +HRESULT SetCurrentAppUserModelID (PCWSTR appID) +{ + typedef HRESULT (WINAPI *SetAppUserModelIDFunc)(PCWSTR); + HMODULE shell32 = LoadLibraryW (L"shell32.dll"); + if (!shell32) return E_FAIL; + auto SetAppUserModelID = (SetAppUserModelIDFunc)GetProcAddress (shell32, "SetCurrentProcessExplicitAppUserModelID"); + if (!SetAppUserModelID) + { + FreeLibrary (shell32); + return E_FAIL; + } + HRESULT hr = SetAppUserModelID (appID); + FreeLibrary (shell32); + return hr; +} + +void ProgressCallback (unsigned progress); + +public ref class MainWnd: public Form +{ + private: + WebBrowser ^webUI; + int page; + System::Collections::Generic::Dictionary ^jsFunctionHandlers; + public: + MainWnd (): page (-1) + { + jsFunctionHandlers = gcnew System::Collections::Generic::Dictionary (); + initWnd (); + } + private: + void initWnd () + { + this->Visible = false; + this->webUI = gcnew WebBrowser (); + this->SuspendLayout (); + this->webUI->Dock = DockStyle::Fill; + this->webUI->DocumentCompleted += gcnew WebBrowserDocumentCompletedEventHandler (this, &MainWnd::eventOnDocumentCompleted); + this->webUI->IsWebBrowserContextMenuEnabled = false; + this->webUI->PreviewKeyDown += gcnew System::Windows::Forms::PreviewKeyDownEventHandler (this, &MainWnd::eventOnPreviewKeyDown_WebBrowser); + this->Controls->Add (this->webUI); + HICON tempIco = LoadRCIcon (ICON_TASKBAR); + if (tempIco) + { + this->Icon = System::Drawing::Icon::FromHandle (IntPtr (tempIco)); + // DestroyIcon (tempIco); + } + unsigned wid = 0, hei = 0; + if (m_initConfig.readBoolValue (L"Settings", L"SavePosBeforeClosing")) + { + wid = m_initConfig.readUIntValue (L"Settings", L"SavePosWidth", + m_initConfig.readUIntValue (L"Settings", L"PosWidth", + (unsigned)_wtol (GetRCString_cpp (INITWIDTH).c_str ()) + ) + ); + hei = m_initConfig.readUIntValue (L"Settings", L"SavePosHeight", + m_initConfig.readUIntValue (L"Settings", L"PosHeight", + (unsigned)_wtol (GetRCString_cpp (INITHEIGHT).c_str ()) + ) + ); + } + else + { + wid = m_initConfig.readUIntValue (L"Settings", L"SavePosWidth", + (unsigned)_wtol (GetRCString_cpp (INITWIDTH).c_str ()) + ); + hei = m_initConfig.readUIntValue (L"Settings", L"SavePosHeight", + (unsigned)_wtol (GetRCString_cpp (INITHEIGHT).c_str ()) + ); + } + this->MinimumSize = System::Drawing::Size ( + m_initConfig.readUIntValue (L"Settings", L"MinPosWidth", (unsigned)_wtol (GetRCString_cpp (LIMITWIDTH).c_str ())), + m_initConfig.readUIntValue (L"Settings", L"MinPosHeight", (unsigned)_wtol (GetRCString_cpp (LIMITHEIGHT).c_str ())) + ); + this->WindowState = (System::Windows::Forms::FormWindowState)m_initConfig.readIntValue (L"Settings", L"WindowPos", (int)System::Windows::Forms::FormWindowState::Normal); + this->ClientSize = System::Drawing::Size (wid, hei); + this->Text = GetRCString (WIN_TITLE); + this->Load += gcnew EventHandler (this, &MainWnd::eventOnCreate); + this->ResizeEnd += gcnew EventHandler (this, &MainWnd::eventOnResizeEnd); + this->ResumeLayout (false); + this->Resize += gcnew System::EventHandler (this, &MainWnd::eventOnResize); + } + void eventOnCreate (System::Object ^sender, System::EventArgs ^e) + { + SetWebBrowserEmulation (); + String ^rootDir = System::IO::Path::GetDirectoryName (System::Windows::Forms::Application::ExecutablePath); + String ^htmlFilePath = System::IO::Path::Combine (rootDir, "HTML\\Index.html"); + if (IsIeVersion10 ()) htmlFilePath = System::IO::Path::Combine (rootDir, "HTML\\IndexIE10.html"); // IE10 (Win8) ع + webUI->Navigate (htmlFilePath); + webUI->ObjectForScripting = this; + } + void eventOnPreviewKeyDown_WebBrowser (System::Object ^sender, System::Windows::Forms::PreviewKeyDownEventArgs ^e) + { + if (e->KeyCode == System::Windows::Forms::Keys::F5 || (e->KeyCode == System::Windows::Forms::Keys::R && e->Control)) + e->IsInputKey = true; + } + void eventOnDocumentCompleted (Object ^sender, WebBrowserDocumentCompletedEventArgs ^e) + { + if (e->Url->ToString () == webUI->Url->ToString ()) + { + eventOnPageLoad (); + } + } + void eventOnResizeEnd (Object ^sender, EventArgs ^e) + { + if (this->WindowState == FormWindowState::Maximized) + { + this->changeMaxDisplayPicJS (true); + } + else if (this->WindowState == FormWindowState::Normal) + { + this->changeMaxDisplayPicJS (false); + } + } + void eventOnResize (Object ^sender, EventArgs ^e) + { + if (this->WindowState == FormWindowState::Maximized) + { + this->changeMaxDisplayPicJS (true); + m_initConfig.writeIntValue (L"Settings", L"WindowPos", (int)this->WindowState); + } + else + { + m_initConfig.writeIntValue (L"Settings", L"WindowPos", 0); + this->changeMaxDisplayPicJS (false); + if (m_initConfig.readBoolValue (L"Settings", L"SavePosBeforeClosing")) + { + m_initConfig.writeUIntValue (L"Settings", L"SavePosWidth", this->Width); + m_initConfig.writeUIntValue (L"Settings", L"SavePosHeight", this->Height); + } + } + } + void eventOnPageLoad () + { + this->Visible = true; + this->setLaunchWhenReadyJS (m_initConfig.readBoolValue (L"Settings", L"LaunchWhenReady", true)); + if (IsIeVersion10 ()) hideFrameJS (false); + Thread ^thread = gcnew Thread (gcnew ThreadStart (this, &MainWnd::taskReadFile)); + thread->Start (); + Thread ^thread2 = gcnew Thread (gcnew ThreadStart (this, &MainWnd::taskCountDarkMode)); + thread2->Start (); + } + void eventOnPress_button1 () + { + //MessageBox::Show ("һ򵥵Ϣ"); + switch (page) + { + case 1: + { + OpenFileDialog^ openFileDialog = gcnew OpenFileDialog (); + openFileDialog->Title = rcString (DIALOG_WINTITLE); + openFileDialog->Filter = rcString (DIALOG_SELLET_APPX) + "|*.appx;*appxbundle|" + rcString (DIALOG_SELLET_UNI) + "|*.*"; + openFileDialog->FilterIndex = 1; + openFileDialog->RestoreDirectory = true; + if (openFileDialog->ShowDialog () == System::Windows::Forms::DialogResult::OK) + { + System::String^ filePath = openFileDialog->FileName; + std::wstring stdFilePath = msclr::interop::marshal_as (filePath); + pkgPath = stdFilePath; + invokeSetPage (0); + Thread ^thread = gcnew Thread (gcnew ThreadStart (this, &MainWnd::taskReadFile)); + thread->SetApartmentState (ApartmentState::STA); + thread->Start (); + } + } break; + case 2: + { + invokeSetPage (3); + Thread ^thread = gcnew Thread (gcnew ThreadStart (this, &MainWnd::taskInstallPackage)); + thread->SetApartmentState (ApartmentState::STA); + thread->Start (); + } break; + case 4: + { + // this->setButtonDisabledJS (true); + if (!m_pkgInfo.isPackageApplication ()) + { + this->Close (); break; + } + else + { + std::vector ids; + m_pkgInfo.getApplicationUserModelIDs (ids); + DWORD dwPId = 0; + if (ids.size () == 1) LaunchApp (ids [0].c_str (), &dwPId); + } + // this->setButtonDisabledJS (false); + } break; + case 5: + { + this->Close (); + } break; + } + } + void eventOnPress_button2 () + { + + } + void eventOnPress_buttonBack () + { + + } + void eventOnPress_buttonOption () + { + + } + void eventOnPress_buttonNext () + { + + } + void eventOnPress_buttonMin () + { + if (this->WindowState == System::Windows::Forms::FormWindowState::Minimized) this->WindowState = System::Windows::Forms::FormWindowState::Normal; + else this->WindowState = System::Windows::Forms::FormWindowState::Minimized; + } + void eventOnPress_buttonMax () + { + if (this->WindowState == System::Windows::Forms::FormWindowState::Maximized) + { + this->WindowState = System::Windows::Forms::FormWindowState::Normal; + this->changeMaxDisplayPicJS (false); + } + else + { + this->WindowState = System::Windows::Forms::FormWindowState::Maximized; + this->changeMaxDisplayPicJS (true); + } + } + void eventOnPress_buttonCancel () + { + this->Close (); + } + Object ^CallJSFunction (String ^functionName, ... array ^args) + { + if (webUI->Document != nullptr) + { + try + { + return webUI->Document->InvokeScript (functionName, args); + } + catch (Exception^ ex) + { + MessageBox::Show ("Error calling JavaScript function: " + ex->Message); + return nullptr; + } + } + return nullptr; + } + void setPageJS (int pageSerial) + { + CallJSFunction ("SetPage", gcnew array { pageSerial }); + } + void setLogoBackgroundColorJS (String ^color) + { + if (color == "transparent") + { + color = ColorToHtml (GetAeroColor ()); + } + CallJSFunction ("setImgBackground", gcnew array { color }); + } + void setLogoBackgroundColorJS (System::Drawing::Color ^color) + { + CallJSFunction ("setImgBackground", gcnew array { color }); + } + void setLaunchWhenReadyJS (bool value) + { + CallJSFunction ("SetLaunchWhenReady", gcnew array { value }); + } + void invokeSetLaunchWhenReady (bool value) + { + if (this->InvokeRequired) + { + this->Invoke (gcnew Action (this, &MainWnd::setLaunchWhenReadyJS), value); + } + else + { + setLaunchWhenReadyJS (value); + } + } + void setDisableLaunchWhenReadyJS (bool value) + { + CallJSFunction ("SetLaunchWhenReadyDisable", gcnew array { value }); + } + void invokeSetDisableLaunchWhenReady (bool value) + { + if (this->InvokeRequired) + { + this->Invoke (gcnew Action (this, &MainWnd::setDisableLaunchWhenReadyJS), value); + } + else + { + setDisableLaunchWhenReadyJS (value); + } + } + bool getLaunchWhenReadyJS () + { + return (bool)CallJSFunction ("GetLaunchWhenReady", gcnew array {}); + } + void setWindowTitleJS (String ^value) + { + CallJSFunction ("SetWindowTitle", gcnew array { value }); + } + void setStoreLogoJS (String ^value) + { + CallJSFunction ("SetStoreLogo", gcnew array { value }); + } + void hideFrameJS (bool value) + { + CallJSFunction ("HideFrame", gcnew array { value }); + } + void setTextJS (String ^comID, String ^content) + { + try + { + CallJSFunction ("SetText", gcnew array { comID, content }); + } + catch (System::Exception^ e) + { + Console::WriteLine ("Error setting text for component '" + comID + "': " + e->Message); + } + } + void setProgressTextJS (String ^content) + { + this->setTextJS ("caption-status", content); + } + void changeMaxDisplayPicJS (bool value) + { + CallJSFunction ("ChangeMaxDisplayPic", gcnew array { value }); + } + size_t getTextLineNumberJS (String ^comID) + { + Object ^result = CallJSFunction ("GetTextLineNumber", gcnew array { comID }); + int lineCount = Convert::ToInt32 (result); + if (lineCount < 0) + { + throw gcnew ArgumentException ("Element with ID '" + comID + "' does not exist."); + } + return static_cast(lineCount); + } + size_t getTextOmitAdviceJS (String ^comID, String ^text, size_t limitLines) + { + Object ^result = CallJSFunction ("GetTextOmitAdvice", gcnew array { comID, text, limitLines }); + int lineCount = Convert::ToInt32 (result); + if (lineCount < 0) + { + throw gcnew ArgumentException ("Element with ID '" + comID + "' does not exist."); + } + return static_cast(lineCount); + } + void setPicBoxVisibilityJS (bool value) + { + + CallJSFunction ("SetPicBoxVisibility", gcnew array { value }); + } + void setButtonDisabledJS (bool value) + { + CallJSFunction ("SetButtonDisabled", gcnew array { value }); + } + void setProgressJS (unsigned value) + { + CallJSFunction ("SetProgress", gcnew array { value }); + } + void setDarkModeJS (bool value) + { + CallJSFunction ("SetDarkMode", gcnew array { value }); + } + void invokeSetDarkMode (bool value) + { + if (this->InvokeRequired) + { + this->Invoke (gcnew Action (this, &MainWnd::setDarkModeJS), value); + } + else + { + setDarkModeJS (value); + } + } + void invokeSetProgress (unsigned value) + { + if (this->InvokeRequired) + { + this->Invoke (gcnew Action (this, &MainWnd::setProgressJS), value); + } + else + { + setProgressJS (value); + } + } + void invokeSetProgressText (String ^content) + { + if (this->InvokeRequired) + { + this->Invoke (gcnew Action (this, &MainWnd::setProgressTextJS), content); + } + else + { + setProgressTextJS (content); + } + } + void setPage (int serial) + { + switch (serial) + { + case 0: + setTextJS ("file-loading-text", rcString (PAGE_LOADING)); + break; + case 1: + setTextJS ("caption-title", rcString (PAGE_3_TITLE)); + setTextJS ("button-serial-1-title", rcString (BUTTON_3_SER1)); + setTextJS ("button-serial-1", rcString (BUTTON_3_SER1)); + break; + case 2: + { + std::wstring title = m_pkgInfo.getPropertyName (), titleF = StrPrintFormatW (GetRCString_cpp (PAGE_1_TITLE).c_str (), title.c_str ()); + size_t reduce = getTextOmitAdviceJS (gcnew String ("caption-title"), gcnew String (titleF.c_str ()), (size_t)2); + std::wstring sub = title.substr (0, title.length () - reduce) + (reduce > 3 ? L"..." : L""); + setTextJS ("caption-title", gcnew String (StrPrintFormatW (GetRCString_cpp (PAGE_1_TITLE).c_str (), sub.c_str ()).c_str ())); + } + setTextJS ("caption-ms-store-app", rcString (PAGE_1_APP)); + setTextJS ("caption-publisher", gcnew String (StrPrintFormatW (GetRCString_cpp (PAGE_INFO_PUBLISHER).c_str (), m_pkgInfo.getPropertyPublisher ().c_str ()).c_str ())); + setTextJS ("caption-version", gcnew String (StrPrintFormatW (GetRCString_cpp (PAGE_INFO_VERSION).c_str (), m_pkgInfo.getIdentityVersion ().toStringW ().c_str ()).c_str ())); + setTextJS ("caption-textarea-title", rcString (PAGE_FUNCTIONS)); + { + std::wstring temp = L""; + std::vector caps; + if (m_pkgInfo.getCapabilities (caps)) + { + for (auto it : caps) + { + temp += L'\u2022'; + temp += GetRCString_cpp (CapabilitiesNameToID (it.c_str ())); + temp += L"\n"; + } + } + VERSION pver = m_pkgInfo.getPrerequisiteOSMinVersion (); + if (!pver.isEmpty ()) + { + temp += StrPrintFormatW (GetRCString_cpp (textSupportSystem).c_str (), GetPrerequistOSVersionText (pver).c_str (), pver.toStringW ().c_str ()); + temp += L"\n"; + } + std::vector avec; + if (m_pkgInfo.getIdentityProcessorArchitecture (avec)) + { + temp += GetRCString_cpp (textSupportCPU); + for (size_t cnt = 0; cnt < avec.size (); cnt ++) + { + switch (avec [cnt]) + { + case APPX_PACKAGE_ARCHITECTURE_NEUTRAL: temp += L"Neutral"; break; + case APPX_PACKAGE_ARCHITECTURE_X86: temp += L"x86"; break; + case APPX_PACKAGE_ARCHITECTURE_X64: temp += L"x64"; break; + case APPX_PACKAGE_ARCHITECTURE_ARM: temp += L"Arm"; break; + default: + if ((UINT)avec [cnt] == 12) temp += L"Arm64"; + } + if (cnt + 1 != avec.size ()) temp += L", "; + } + temp += L"\n"; + } + std::vector deps; + if (m_pkgInfo.getDependencies (deps)) + { + temp += GetRCString_cpp (textDependency) + L"\n"; + for (size_t cnt = 0; cnt < deps.size (); cnt ++) + { + temp += StrPrintFormatW (GetRCString_cpp (textDependencyItem).c_str (), deps [cnt].name.c_str (), deps [cnt].versionMin.toStringW ().c_str ()); + temp += L"\n"; + } + } + std::vector lvec; + if (m_pkgInfo.getResourceLanguages (lvec)) + { + WCHAR buf [86] = {0}; + for (auto it : lvec) + { + int res = GetLocaleInfoEx (it.c_str (), 2, buf, 86); + if (lstrlenW (buf) > 0) + { + temp += L'\u2022' + std::wstring (buf) + L"\n"; + } + } + } + setTextJS ("caption-more-info", gcnew String (temp.c_str ())); + } + setTextJS ("caption-check-box-label", rcString (PAGE_CHECK_RUNWHENREADY)); + setTextJS ("button-serial-1-title", rcString (BUTTON_1_SER1)); + setTextJS ("button-serial-1", rcString (BUTTON_1_SER1)); + break; + case 3: + { + invokeSetProgressText (rcString (PAGE_2_LOADING)); + std::wstring title = m_pkgInfo.getPropertyName (), titleF = StrPrintFormatW (GetRCString_cpp (PAGE_2_TITLE).c_str (), title.c_str ()); + size_t reduce = getTextOmitAdviceJS (gcnew String ("caption-title"), gcnew String (titleF.c_str ()), (size_t)2); + std::wstring sub = title.substr (0, title.length () - reduce) + (reduce > 3 ? L"..." : L""); + setTextJS ("caption-title", gcnew String (StrPrintFormatW (GetRCString_cpp (PAGE_2_TITLE).c_str (), sub.c_str ()).c_str ())); + } + break; + case 4: + { + std::wstring title = m_pkgInfo.getPropertyName (), titleF = StrPrintFormatW (GetRCString_cpp (PAGE_4_TITLE).c_str (), title.c_str ()); + size_t reduce = getTextOmitAdviceJS (gcnew String ("caption-title"), gcnew String (titleF.c_str ()), (size_t)2); + std::wstring sub = title.substr (0, title.length () - reduce) + (reduce > 3 ? L"..." : L""); + setTextJS ("caption-title", gcnew String (StrPrintFormatW (GetRCString_cpp (PAGE_4_TITLE).c_str (), sub.c_str ()).c_str ())); + } + { + std::vector avec; + if (m_pkgInfo.getApplicationUserModelIDs (avec)) + { + setTextJS ("button-serial-1-title", rcString (BUTTON_4_SER1)); + setTextJS ("button-serial-1", rcString (BUTTON_4_SER1)); + } + else + { + setTextJS ("button-serial-1-title", rcString (BUTTON_5_SER1)); + setTextJS ("button-serial-1", rcString (BUTTON_5_SER1)); + } + } + break; + case 5: + { + std::wstring title = m_pkgInfo.getPropertyName (), titleF = StrPrintFormatW (GetRCString_cpp (PAGE_5_TITLE).c_str (), title.c_str ()); + size_t reduce = getTextOmitAdviceJS (gcnew String ("caption-title"), gcnew String (titleF.c_str ()), (size_t)2); + std::wstring sub = title.substr (0, title.length () - reduce) + (reduce > 3 ? L"..." : L""); + setTextJS ("caption-title", gcnew String (StrPrintFormatW (GetRCString_cpp (PAGE_5_TITLE).c_str (), sub.c_str ()).c_str ())); + if (GetLastErrorDetailTextLength ()) setTextJS ("caption-more-info", gcnew String (GetLastErrorDetailText ())); + else setTextJS ("caption-more-info", gcnew String (L"")); + } + setTextJS ("button-serial-1-title", rcString (BUTTON_5_SER1)); + setTextJS ("button-serial-1", rcString (BUTTON_5_SER1)); + } + setPageJS (serial); + if (serial > 1) + { + std::string res = m_pkgInfo.getPropertyLogoBase64 (); + if (!res.empty () && res.length () > 0) + { + std::string b64logo = res; + // MessageBox::Show (gcnew String ((std::string ("Base 64 String: ") + b64logo).c_str ())); + this->setStoreLogoJS (gcnew String (res.c_str ())); + setPicBoxVisibilityJS (true); + } + else setPicBoxVisibilityJS (false); + } + else + { + setPicBoxVisibilityJS (false); + } + page = serial; + } + void invokeSetPage (int page) + { + if (this->InvokeRequired) + { + this->Invoke (gcnew Action (this, &MainWnd::setPage), page); + } + else + { + setPage (page); + } + } + void invokeSetColor (String ^color) + { + if (this->InvokeRequired) + { + this->Invoke (gcnew Action (this, &MainWnd::setLogoBackgroundColorJS), color); + } + else + { + setLogoBackgroundColorJS (color); + } + } + void setTaskbarProgress (int progress) + { + IntPtr hwnd = this->Handle; + ITaskbarList3* pTaskbarList = nullptr; + HRESULT hr = CoCreateInstance (CLSID_TaskbarList, nullptr, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, (void**)&pTaskbarList); + if (SUCCEEDED (hr) && pTaskbarList) + { + pTaskbarList->HrInit (); + pTaskbarList->SetProgressState ((HWND)hwnd.ToPointer (), TBPF_NORMAL); + pTaskbarList->SetProgressValue ((HWND)hwnd.ToPointer (), progress, 100); + pTaskbarList->Release (); + } + } + void clearTaskbarProgress () + { + IntPtr hwnd = this->Handle; + // ȡ ITaskbarList3 ӿ + ITaskbarList3* pTaskbarList = nullptr; + HRESULT hr = CoCreateInstance (CLSID_TaskbarList, nullptr, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, (void**)&pTaskbarList); + if (SUCCEEDED (hr) && pTaskbarList) + { + pTaskbarList->HrInit (); + // ״̬ + pTaskbarList->SetProgressState ((HWND)hwnd.ToPointer (), TBPF_NOPROGRESS); + // ͷ ITaskbarList3 ӿ + pTaskbarList->Release (); + } + } + bool invokeGetLaunchWhenReady () + { + if (this->InvokeRequired) + { + return (bool)this->Invoke (gcnew Func (this, &MainWnd::getLaunchWhenReadyJS)); + } + else + { + return getLaunchWhenReadyJS (); + } + } + [STAThread] + void taskReadFile () + { + m_pkgInfo.destroy (); + if (IsFileExistsW (pkgPath.c_str ())) reader.create (pkgPath); + if (reader.isAvailable ()) + { + m_pkgInfo.create (reader); + std::vector color; + m_pkgInfo.getApplicationVisualElementsBackgroundColor (color); + // if (page < 0) invokeSetPage (2); + if (color.size () > 0) + { + invokeSetColor (gcnew String (color [0].c_str ())); + } + invokeSetPage (2); + if (m_silentMode) + { + invokeSetDisableLaunchWhenReady (true); + invokeSetLaunchWhenReady (false); + invokeSetPage (3); + Thread ^thread = gcnew Thread (gcnew ThreadStart (this, &MainWnd::taskInstallPackage)); + thread->SetApartmentState (ApartmentState::STA); + thread->Start (); + } + } + else + { + if (m_silentMode) + { + // ڴ˰汾УھĬģʽ´ЧİԶرմڽ + this->Close (); + } + else + { + invokeSetPage (1); + } + } + this->invokeSetDarkMode (IsAppInDarkMode ()); + EmptyWorkingSet ((HANDLE)-1); + } + void taskInstallPackage () + { + invokeSetProgressText (rcString (PAGE_2_LOADCERT)); + /* + std::vector cerfiles; + EnumerateFilesW (GetFileDirectoryW (pkgPath.c_str ()), L"*.cer", cerfiles, false); + for (auto it : cerfiles) + { + bool res = LoadCertFromCertFile (it.c_str ()); + std::wstring outputDe = L"File: " + it + L", Result: " + (res ? L"true" : L"false"); + OutputDebugStringW (outputDe.c_str ()); + } + */ + LoadCertFromSignedFile (pkgPath.c_str ()); + invokeSetProgressText (rcString (PAGE_2_INSTALL)); + InstallStatus status = AddPackageFromPath (pkgPath.c_str (), &ProgressCallback); + // MessageBeep (MB_OK); + if (status == InstallStatus::Success) + { + invokeSetPage (4); + if (this->invokeGetLaunchWhenReady ()) + { + if (reader.isPackageApplication ()) this->eventOnPress_button1 (); // APP + } + Thread ^closeThread = gcnew Thread (gcnew ThreadStart (this, &MainWnd::taskCountCancel)); + closeThread->IsBackground = true; + closeThread->Start (); + } + else + { + invokeSetPage (5); + if (m_silentMode) + { + Thread ^closeThread = gcnew Thread (gcnew ThreadStart (this, &MainWnd::taskCountCancel)); + closeThread->IsBackground = true; + closeThread->Start (); + } + } + this->clearTaskbarProgress (); + std::wstring title = StrPrintFormatW (GetRCString_cpp (PAGE_4_TITLE).c_str (), m_pkgInfo.getPropertyName ().c_str ()); + std::wstring text (L""); + if (GetLastErrorDetailTextLength ()) text += GetLastErrorDetailText (); + bool res = CreateToastNotification (m_idenName, title.c_str (), text.c_str (), NULL, m_pkgInfo.getPropertyLogoIStream ()); + #ifdef _DEBUG + //MessageBox::Show (res ? "Toast has create! " : "Toast created failed! "); + #endif + EmptyWorkingSet ((HANDLE)-1); + } + void taskCountCancel () + { + for (char cnt = 0; cnt < 100; cnt ++) + { + if (!this->IsHandleCreated) break; + Thread::Sleep (50); + } + if (this->IsHandleCreated) + { + this->Invoke (gcnew MethodInvoker (this, &MainWnd::Close)); + } + } + void taskCountDarkMode () + { + for (char cnt = 0; cnt < 8; cnt ++) + { + if (!this->IsHandleCreated) + { + break; + } + else + { + if (!this->webUI->IsHandleCreated) + { + break; + } + } + Thread::Sleep (50); + } + if (this->IsHandleCreated) + { + if (this->webUI->IsHandleCreated) + { + this->invokeSetDarkMode (IsAppInDarkMode ()); + } + } + } + public: + [STAThread] + void Button1_PressEvent () { eventOnPress_button1 (); } + [STAThread] + void Button2_PressEvent () { eventOnPress_button2 (); } + [STAThread] + void PageBackEvent () { eventOnPress_buttonBack (); } + [STAThread] + void WinOptionEvent () { eventOnPress_buttonOption (); } + [STAThread] + void PageNextEvent () { eventOnPress_buttonNext (); } + [STAThread] + void WinMinEvent () { eventOnPress_buttonMin (); } + [STAThread] + void WinMaxEvent () { eventOnPress_buttonMax (); } + [STAThread] + void WinCancelEvent () { eventOnPress_buttonCancel (); } + void funcSetProgress (unsigned value) + { + this->invokeSetProgress (value); + invokeSetProgressText ( + gcnew String ( + StrPrintFormatW (GetRCString_cpp (PAGE_2_INSTALLING).c_str (), (int)value).c_str () + ) + ); + this->setTaskbarProgress ((unsigned)value); + } +}; + +typedef struct _CMDARGUMENT +{ + std::vector front; + std::vector body; + std::vector rear; + int flag; +} CMDARGUMENT; + +std::vector cmdargs = +{ + {{L"", L"/", L"-"}, {L"DISABLEFRAME", L"NOCUSTOM", L"WIN32FRAME", L"ORIGINALBORDER"}, {}, 1}, + {{L"", L"/", L"-"}, {L"SILENT", L"QUIET", L"PASSIVE"}, {}, 2}, + {{L"", L"/", L"-"}, {L"VERYSILENT", L"VERYQUIET"}, {}, 3}, + {{L"", L"/", L"-"}, {L"NOGUI", L"CMD"}, {}, 4}, + {{L"", L"/", L"-"}, {L"HELP", L"?", L"H"}, {}, 5}, + {{L"", L"/", L"-"}, {L"ENABLEFRAME", L"CUSTOM", L"EXFRAME", L"CUSTOMBORDER", L"NEWFRAME"}, {}, 6}, + {{L"", L"/", L"-"}, {L"WIN32WINDOW", L"USEWIN32", L"USEWIN32WINDOW", L"NOWEBUI", L"DISABLEWEBUI"}, {}, 7}, + {{L"", L"/", L"-"}, {L"CREATESHORTCUT", L"SHORTCUT", L"CREATELNK"}, {}, 8}, + {{L"", L"/", L"-"}, {L"DELETESHORTCUT", L"DELSHORTCUT", L"DELETELNK"}, {}, 9}, + {{L"", L"/", L"-"}, {L"DEVTOOL", L"DEVTOOLS", L"DEVMODE", L"DEVELOP"}, {}, 10}, + {{L"", L"/", L"-"}, {L"USEEPROGRAM", L"EPROGRAM", L"ESUPPORT", L"USEE"}, {}, 11} +}; + +// Ϊ 0 ʧܷط +int GetCmdArgSerial (std::wstring cmdparam) +{ +#define tolabel(__std_wstring__) StringToUpper (StringTrim (__std_wstring__)) + std::wstring arg = tolabel (cmdparam); + for (size_t cnt = 0; cnt < cmdargs.size (); cnt ++) + { + CMDARGUMENT &tca = cmdargs [cnt]; + std::wstring tempP = L""; + for (size_t i = 0; i < tca.body.size (); i ++) + { + if (tca.rear.size () > 0) + { + if (tca.front.size () > 0) + { + for (size_t j = 0; j < tca.front.size (); j ++) + { + for (size_t k = 0; k < tca.rear.size (); k ++) + { + tempP = tolabel (tca.front [j]) + tolabel (tca.body [i]) + tolabel (tca.rear [k]); + std::wstring t1; + if (tolabel (tca.rear [k]).length () > 0) t1 = arg.substr (0, tempP.length ()); + else t1 = tempP; + if (t1 == arg) return tca.flag; + } + } + } + else + { + for (size_t k = 0; k < tca.rear.size (); k ++) + { + tempP = tolabel (tca.body [i]) + tolabel (tca.rear [k]); + std::wstring t1; + if (tolabel (tca.rear [k]).length () > 0) t1 = arg.substr (0, tempP.length ()); + else t1 = tempP; + if (t1 == arg) return tca.flag; + } + } + } + else + { + if (tca.front.size () > 0) + { + for (size_t j = 0; j < tca.front.size (); j ++) + { + tempP = tolabel (tca.front [j]) + tolabel (tca.body [i]); + std::wstring &t1 = tempP; + if (t1 == arg) return tca.flag; + } + } + else + { + tempP = tolabel (tca.body [i]); + std::wstring &t1 = tempP; + if (t1 == arg) return tca.flag; + } + } + } + } + return 0; // 0 C/C++ ߼ж +} +int GetCmdArgSerial (LPCWSTR cmdparam) { return GetCmdArgSerial (std::wstring (cmdparam)); } + +// ʱִ GUI +[MTAThread] +bool ReadCommand (int argc, LPWSTR *argv) +{ + std::vector vecObjSwFiles; + bool bWin32Wnd = false, bSilent = false, bVerySilent = false, + bUseConsole = false, bUseNewFrame = false, bDisplayHelp = false, + bCreateLnk = false, bDestroyLnk = false, bDevTool = false, + bUseEProgream = false; + for (size_t cnt = 0; cnt < (size_t)argc; cnt ++) + { + int res = GetCmdArgSerial (argv [cnt]); + if (res > 0) + { + switch (res) + { + case 1: bUseNewFrame = false; break; + case 2: bSilent = true; break; + case 3: bVerySilent = true; break; + case 4: bUseConsole = true; break; + case 5: bDisplayHelp = true; break; + case 6: bUseNewFrame = true; break; + case 7: bWin32Wnd = true; break; + case 8: bCreateLnk = true; break; + case 9: bDestroyLnk = true; break; + case 10: bDevTool = true; break; + case 11: bUseEProgream = true; break; + } + } + else + { + if (IsFileExistsW (argv [cnt])) push_no_repeat (vecObjSwFiles, argv [cnt]); + } + } + bWin32Wnd = bWin32Wnd | !m_initConfig.readBoolValue (L"Settings", L"UseWebUI", true); + bUseEProgream = bUseEProgream | m_initConfig.readBoolValue (L"Settings", L"UseElderWebUI", false); + bUseNewFrame = bUseNewFrame | m_initConfig.readBoolValue (L"WebUI", L"UseNewFrame", false); + if (bDisplayHelp) // ʾ + { + MessageBox::Show ( + rcString (CLHELP_1) + + rcString (CLHELP_2) + + rcString (CLHELP_4) + + rcString (CLHELP_5) + + rcString (CLHELP_7) + ); + return false; + } + if (bCreateLnk) + { + WCHAR expandedPath [MAX_PATH]; + ExpandEnvironmentStringsW (L"%ProgramData%\\Microsoft\\Windows\\Start Menu\\Programs\\Desktop App Installer", expandedPath, MAX_PATH); + if (IsDirectoryExists (expandedPath) || CreateDirectoryW (expandedPath, NULL)) + { + WCHAR lnkPath [MAX_PATH]; + PathCombineW (lnkPath, expandedPath, L"App Installer.lnk"); + WCHAR path [MAX_PATH] = {0}; + GetModuleFileNameW (NULL, path, MAX_PATH); + HRESULT hr = CreateShortcutWithAppIdW (lnkPath, path, m_idenName); + if (SUCCEEDED (hr)) + { + WCHAR desktopIni [MAX_PATH]; + PathCombineW (desktopIni, expandedPath, L"desktop.ini"); + WInitFile desktop (desktopIni); + WCHAR resIdStr [16] = {0}; + _itow (WIN_TITLE, resIdStr, 10); + desktop.writeUIntValue (L".ShellClassInfo", L"ConfirmFileOp", 0); + desktop.writeStringValue (L"LocalizedFileNames", L"App Installer.lnk", std::wstring (L"@") + path + L",-" + resIdStr); + DWORD attrs = GetFileAttributesW (desktopIni); + SetFileAttributesW (desktopIni, attrs | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM); + DWORD folderAttrs = GetFileAttributesW (expandedPath); + SetFileAttributesW (expandedPath, folderAttrs | FILE_ATTRIBUTE_SYSTEM); + } + } + return false; + } + if (bDestroyLnk) + { + WCHAR expandedPath [MAX_PATH]; + if (ExpandEnvironmentStringsW (L"%ProgramData%\\Microsoft\\Windows\\Start Menu\\Programs\\Desktop App Installer", expandedPath, MAX_PATH)) + { + if (IsDirectoryExists (expandedPath)) + { + WCHAR lnkPath [MAX_PATH]; + PathCombineW (lnkPath, expandedPath, L"App Installer.lnk"); + DeleteFileW (lnkPath); + } + } + return false; + } + m_silentMode = bSilent || bVerySilent; // Զģʽ + if (vecObjSwFiles.size () == 1) + { + pkgPath = vecObjSwFiles [0]; + if (bVerySilent) // Ĭģʽʱֻװʾ GUI + { + LoadCertFromSignedFile (pkgPath.c_str ()); + AddPackageFromPath (pkgPath.c_str (), NULL); + return false; + } + else if (bWin32Wnd) + { + std::wstring root = EnsureTrailingSlash (GetProgramRootDirectoryW ()); + std::wstring exepath = root + L"AppInstaller_win32.exe"; + std::wstring args = L""; + args += L"\"" + pkgPath + L"\" "; + if (bUseNewFrame) args += L"/ENABLEFRAME "; + else args += L"/DISABLEFRAME "; + if (bSilent) args += L"/SILENT "; + if (bVerySilent) args += L"/VERYSILENT "; + if (bUseConsole) args += L"/NOGUI "; + if (bDisplayHelp) args += L"/? "; + std::wstring cmdline = L"\"" + exepath + L"\" " + args; + { + STARTUPINFOW si = {sizeof (STARTUPINFOW)}; + PROCESS_INFORMATION pi = {0}; + if (CreateProcessW (NULL, (LPWSTR)cmdline.c_str (), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) + { + WaitForSingleObject (pi.hProcess, INFINITE); + CloseHandle (pi.hProcess); + CloseHandle (pi.hThread); + return false; + } + } + } + else if (bUseEProgream) + { + std::wstring root = EnsureTrailingSlash (GetProgramRootDirectoryW ()); + std::wstring exepath = root + L"AppInstallerE.exe"; + std::wstring args = L""; + args += L"\"" + pkgPath + L"\" "; + if (bUseNewFrame) args += L"/ENABLEFRAME "; + else args += L"/DISABLEFRAME "; + if (bSilent) args += L"/SILENT "; + if (bVerySilent) args += L"/VERYSILENT "; + if (bUseConsole) args += L"/NOGUI "; + if (bDisplayHelp) args += L"/? "; + std::wstring cmdline = L"\"" + exepath + L"\" " + args; + { + STARTUPINFOW si = {sizeof (STARTUPINFOW)}; + PROCESS_INFORMATION pi = {0}; + if (CreateProcessW (NULL, (LPWSTR)cmdline.c_str (), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) + { + WaitForSingleObject (pi.hProcess, INFINITE); + CloseHandle (pi.hProcess); + CloseHandle (pi.hThread); + return false; + } + } + } + else if (bUseConsole) + { + std::wstring root = EnsureTrailingSlash (GetProgramRootDirectoryW ()); + std::wstring exepath = root + L"WSAppPkgIns.exe"; + std::wstring args = L""; + args += L"\"" + pkgPath + L"\" "; + std::wstring cmdline = L"\"" + exepath + L"\" " + args; + { + STARTUPINFOW si = {sizeof (STARTUPINFOW)}; + PROCESS_INFORMATION pi = {0}; + if (CreateProcessW (NULL, (LPWSTR)cmdline.c_str (), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) + { + WaitForSingleObject (pi.hProcess, INFINITE); + CloseHandle (pi.hProcess); + CloseHandle (pi.hThread); + return false; + } + } + } + return true; + } + else if (vecObjSwFiles.size () <= 0) + { + if (bWin32Wnd) + { + std::wstring root = EnsureTrailingSlash (GetProgramRootDirectoryW ()); + std::wstring exepath = root + L"AppInstaller_win32.exe"; + std::wstring args = L""; + if (bUseNewFrame) args += L"/ENABLEFRAME "; + else args += L"/DISABLEFRAME "; + if (bSilent) args += L"/SILENT "; + if (bVerySilent) args += L"/VERYSILENT "; + if (bUseConsole) args += L"/NOGUI "; + if (bDisplayHelp) args += L"/? "; + std::wstring cmdline = L"\"" + exepath + L"\" " + args; + { + STARTUPINFOW si = {sizeof (STARTUPINFOW)}; + PROCESS_INFORMATION pi = {0}; + if (CreateProcessW (NULL, (LPWSTR)cmdline.c_str (), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) + { + WaitForSingleObject (pi.hProcess, INFINITE); + CloseHandle (pi.hProcess); + CloseHandle (pi.hThread); + return false; + } + } + } + else if (bUseEProgream) + { + std::wstring root = EnsureTrailingSlash (GetProgramRootDirectoryW ()); + std::wstring exepath = root + L"AppInstallerE.exe"; + std::wstring args = L""; + if (bUseNewFrame) args += L"/ENABLEFRAME "; + else args += L"/DISABLEFRAME "; + if (bSilent) args += L"/SILENT "; + if (bVerySilent) args += L"/VERYSILENT "; + if (bUseConsole) args += L"/NOGUI "; + if (bDisplayHelp) args += L"/? "; + if (bDevTool) args += L"/DEVTOOL "; + std::wstring cmdline = L"\"" + exepath + L"\" " + args; + { + STARTUPINFOW si = {sizeof (STARTUPINFOW)}; + PROCESS_INFORMATION pi = {0}; + if (CreateProcessW (NULL, (LPWSTR)cmdline.c_str (), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) + { + WaitForSingleObject (pi.hProcess, INFINITE); + CloseHandle (pi.hProcess); + CloseHandle (pi.hThread); + return false; + } + } + } + else return true; + } + else if (vecObjSwFiles.size () > 1) // Զļ + { + for (auto it : vecObjSwFiles) + { + wchar_t path [MAX_PATH] = {0}; + if (GetModuleFileNameW (NULL, path, MAX_PATH)) + { + std::wstring args = L""; + args += L"\"" + it + L"\" "; + if (bUseNewFrame) args += L"/ENABLEFRAME "; + else args += L"/DISABLEFRAME "; + if (bSilent) args += L"/SILENT "; + if (bVerySilent) args += L"/VERYSILENT "; + if (bUseConsole) args += L"/NOGUI "; + if (bDisplayHelp) args += L"/? "; + if (bWin32Wnd) args += L"WIN32WINDOW "; + if (bUseEProgream) args += L"/USEEPROGRAM "; + std::wstring cmdline = L"\"" + std::wstring (path) + L"\" " + args; + { + STARTUPINFOW si = {sizeof (STARTUPINFOW)}; + PROCESS_INFORMATION pi = {0}; + if (CreateProcessW (NULL, (LPWSTR)cmdline.c_str (), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) + { + WaitForSingleObject (pi.hProcess, INFINITE); + CloseHandle (pi.hProcess); + CloseHandle (pi.hThread); + } + } + } + } + return false; + } + return false; +} + +// ʱִ GUI +[MTAThread] +bool ReadCommand (LPWSTR lpCmdLine) +{ + int iArgc = 0; + LPWSTR *lpArgv = CommandLineToArgvW (lpCmdLine, &iArgc); + return ReadCommand (iArgc, lpArgv); +} + +msclr::gcroot mainwndPtr; +void SetProgressDisplayWnd (MainWnd ^ptr) +{ + mainwndPtr = ptr; +} +void ProgressCallback (unsigned progress) +{ + mainwndPtr->funcSetProgress (progress); +} + +void OutputDebugStringFormatted (const wchar_t* format, ...) +{ + wchar_t buffer [1024]; + va_list args; + va_start (args, format); + vswprintf (buffer, sizeof (buffer) / sizeof (wchar_t), format, args); + va_end (args); + OutputDebugString (buffer); +} + +[STAThread] +int APIENTRY wWinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) +{ + SetCurrentProcessExplicitAppUserModelID (m_idenName); + wchar_t currentPath [MAX_PATH]; + GetCurrentDirectory (MAX_PATH, currentPath); + wchar_t executablePath [MAX_PATH]; + GetModuleFileName (NULL, executablePath, MAX_PATH); + std::wstring executableDir (executablePath); + executableDir = executableDir.substr (0, executableDir.find_last_of (L"\\/")); + if (!wcscmp (currentPath, executableDir.c_str ())) + { + SetCurrentDirectory (executableDir.c_str ()); + } + OutputDebugStringFormatted (L"Current Dir: %ls\n", executableDir.c_str ()); + m_initConfig.setFilePath (EnsureTrailingSlash (GetProgramRootDirectoryW ()) + L"Config.ini"); + CoInitializeEx (NULL, COINIT_MULTITHREADED); + Application::EnableVisualStyles (); + Application::SetCompatibleTextRenderingDefault (false); + MainWnd ^mwnd = gcnew MainWnd (); + SetProgressDisplayWnd (mwnd); + if (ReadCommand (lpCmdLine)) + { + Application::Run (mwnd); + } + reader.destroy (); + return 0; +} \ No newline at end of file diff --git a/AppInstaller/pkgcode.h b/AppInstaller/pkgcode.h new file mode 100644 index 0000000..94ea728 --- /dev/null +++ b/AppInstaller/pkgcode.h @@ -0,0 +1,2062 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +template void push_no_repeat (std::vector &vec, t1 &member) +{ + for (size_t cnt = 0; cnt < vec.size (); cnt ++) if (member == vec [cnt]) return; + vec.push_back (member); +} +template void push_no_repeat (std::vector &vec, t &member) +{ + for (size_t cnt = 0; cnt < vec.size (); cnt ++) if (member == vec [cnt]) return; + vec.push_back (member); +} +#define spush_no_repeat push_no_repeat + +typedef IAppxPackageReader *IAPPXREADER; +typedef IAppxBundleReader *IBUNDLEREADER; + +extern "C" bool IsFileExistsW (LPCWSTR filename) +{ + DWORD dwAttrib = GetFileAttributesW (filename); + return (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)); +} +extern "C" 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 ()); } + +void GetCapabilitiesName (APPX_CAPABILITIES caps, std::vector &output) +{ + if (!&output) return; + ULONG packageCap = (ULONG)caps; + if (packageCap & APPX_CAPABILITY_INTERNET_CLIENT) spush_no_repeat (output, L"internetClient"); + if (packageCap & APPX_CAPABILITY_INTERNET_CLIENT_SERVER) spush_no_repeat (output, L"internetClientServer"); + if (packageCap & APPX_CAPABILITY_PRIVATE_NETWORK_CLIENT_SERVER) spush_no_repeat (output, L"privateNetworkClientServer"); + if (packageCap & APPX_CAPABILITY_DOCUMENTS_LIBRARY) spush_no_repeat (output, L"documentsLibrary"); + if (packageCap & APPX_CAPABILITY_PICTURES_LIBRARY) spush_no_repeat (output, L"picturesLibrary"); + if (packageCap & APPX_CAPABILITY_VIDEOS_LIBRARY) spush_no_repeat (output, L"videosLibrary"); + if (packageCap & APPX_CAPABILITY_MUSIC_LIBRARY) spush_no_repeat (output, L"musicLibrary"); + if (packageCap & APPX_CAPABILITY_ENTERPRISE_AUTHENTICATION) spush_no_repeat (output, L"enterpriseAuthentication"); + if (packageCap & APPX_CAPABILITY_SHARED_USER_CERTIFICATES) spush_no_repeat (output, L"sharedUserCertificates"); + if (packageCap & APPX_CAPABILITY_REMOVABLE_STORAGE) spush_no_repeat (output, L"removableStorage"); + if (packageCap & 1024) spush_no_repeat (output, L"appointments"); //APPX_CAPABILITY_APPOINTMENTS + if (packageCap & 2048) spush_no_repeat (output, L"contacts"); //APPX_CAPABILITY_CONTACTS + if (packageCap & 0x00001000) spush_no_repeat (output, L"phoneCall"); //APPX_CAPABILITY_PHONE_CALL + if (packageCap & 0x00002000) spush_no_repeat (output, L"blockedChatMessages"); //APPX_CAPABILITY_BLOCKED_CHAT_MESSAGES + if (packageCap & 0x00004000) spush_no_repeat (output, L"objects3D"); //APPX_CAPABILITY_OBJECTS3D + if (packageCap & 0x00008000) spush_no_repeat (output, L"allJoyn"); //APPX_CAPABILITY_ALLJOYN + if (packageCap & 0x00010000) spush_no_repeat (output, L"codeGeneration"); //APPX_CAPABILITY_CODE_GENERATION + if (packageCap & 0x00020000) spush_no_repeat (output, L"remoteSystem"); //APPX_CAPABILITY_REMOTE_SYSTEM + if (packageCap & 0x00040000) spush_no_repeat (output, L"userAccountInformation"); //APPX_CAPABILITY_USER_ACCOUNT_INFORMATION + if (packageCap & 0x00080000) spush_no_repeat (output, L"extendedExecution"); //APPX_CAPABILITY_EXTENDED_EXECUTION + if (packageCap & 0x00100000) spush_no_repeat (output, L"location"); //APPX_CAPABILITY_LOCATION + if (packageCap & 0x00200000) spush_no_repeat (output, L"microphone"); //APPX_CAPABILITY_MICROPHONE + if (packageCap & 0x00400000) spush_no_repeat (output, L"proximity"); //APPX_CAPABILITY_PROXIMITY + if (packageCap & 0x00800000) spush_no_repeat (output, L"webcam"); //APPX_CAPABILITY_WEBCAM + if (packageCap & 0x01000000) spush_no_repeat (output, L"spatialPerception"); //APPX_CAPABILITY_SPATIAL_PERCEPTION + if (packageCap & 0x02000000) spush_no_repeat (output, L"appointmentsSystem"); //APPX_CAPABILITY_APPOINTMENTS_SYSTEM + if (packageCap & 0x04000000) spush_no_repeat (output, L"contactsSystem"); //APPX_CAPABILITY_CONTACTS_SYSTEM + if (packageCap & 0x08000000) spush_no_repeat (output, L"phoneCallSystem"); //APPX_CAPABILITY_PHONE_CALL_SYSTEM + if (packageCap & 0x10000000) spush_no_repeat (output, L"smsSend"); //APPX_CAPABILITY_SMS_SEND + if (packageCap & 0x20000000) spush_no_repeat (output, L"userDataTasks"); //APPX_CAPABILITY_USER_DATA_TASKS + if (packageCap & 0x40000000) spush_no_repeat (output, L"userDataTasksSystem"); //APPX_CAPABILITY_USER_DATA_TASKS_SYSTEM + if (packageCap & 0x80000000) spush_no_repeat (output, L"userDataAccounts"); //APPX_CAPABILITY_USER_DATA_ACCOUNTS +} + +HRESULT GetBundleReader (_In_ LPCWSTR inputFileName, _Outptr_ IAppxBundleReader** bundleReader) +{ + HRESULT hr = S_OK; + IAppxBundleFactory* appxBundleFactory = NULL; + IStream* inputStream = NULL; + hr = CoCreateInstance (__uuidof(AppxBundleFactory), NULL, CLSCTX_INPROC_SERVER, __uuidof(IAppxBundleFactory), (LPVOID*)(&appxBundleFactory)); + if (SUCCEEDED (hr)) + { + hr = SHCreateStreamOnFileEx (inputFileName, STGM_READ | STGM_SHARE_DENY_NONE, 0, FALSE, NULL, &inputStream); + } + if (SUCCEEDED (hr)) + { + hr = appxBundleFactory->CreateBundleReader (inputStream, bundleReader); + } + if (inputStream != NULL) + { + inputStream->Release (); + inputStream = NULL; + } + if (appxBundleFactory != NULL) + { + appxBundleFactory->Release (); + appxBundleFactory = NULL; + } + return hr; +} +HRESULT GetPackageReader (_In_ LPCWSTR inputFileName, _Outptr_ IAppxPackageReader** reader) +{ + HRESULT hr = S_OK; + IAppxFactory* appxFactory = NULL; + IStream* inputStream = NULL; + hr = CoCreateInstance (__uuidof(AppxFactory), NULL, CLSCTX_INPROC_SERVER, __uuidof(IAppxFactory), (LPVOID*)(&appxFactory)); + if (SUCCEEDED (hr)) + { + hr = SHCreateStreamOnFileEx (inputFileName, STGM_READ | STGM_SHARE_DENY_NONE, 0, FALSE, NULL, &inputStream); + } + if (SUCCEEDED (hr)) hr = appxFactory->CreatePackageReader (inputStream, reader); + if (inputStream != NULL) + { + inputStream->Release (); + inputStream = NULL; + } + if (appxFactory != NULL) + { + appxFactory->Release (); + appxFactory = NULL; + } + return hr; +} +HRESULT GetAppxPackageReader (_In_ IStream* inputStream, _Outptr_ IAppxPackageReader** packageReader) +{ + HRESULT hr = S_OK; + IAppxFactory* appxFactory = NULL; + hr = CoCreateInstance (__uuidof(AppxFactory), NULL, CLSCTX_INPROC_SERVER, __uuidof(IAppxFactory), (LPVOID*)(&appxFactory)); + if (SUCCEEDED (hr)) + { + hr = appxFactory->CreatePackageReader (inputStream, packageReader); + } + if (appxFactory != NULL) + { + appxFactory->Release (); + appxFactory = NULL; + } + return hr; +} + +typedef struct VERSION +{ + UINT16 build, maintenance, minor, major; + VERSION (UINT16 major, UINT16 minor, UINT16 maintenance, UINT16 build); + VERSION (UINT64 ver); + VERSION (); + virtual ~VERSION (); + std::wstring toStringW (); + std::string toString (); + bool isEmpty (); + UINT64 getUInt64 (); + INT64 compare (VERSION &another); + bool equals (VERSION &another); + bool operator == (VERSION &another) { return this->equals (another); } + bool operator > (VERSION &another) { return this->getUInt64 () > another.getUInt64 (); } + bool operator < (VERSION &another) { return this->getUInt64 () < another.getUInt64 (); } + bool operator >= (VERSION &another) { return !(*this < another); } + bool operator <= (VERSION &another) { return !(*this > another); } + bool operator != (VERSION &another) { return !this->equals (another); } + static VERSION stringTo (const std::string &str); + static VERSION stringTo (const std::wstring &str); + static VERSION stringTo (LPCSTR str); + static VERSION stringTo (LPCWSTR str); + VERSION setFromString (const std::string &str) + { + VERSION v = stringTo (str); + this->major = v.major; + this->minor = v.minor; + this->maintenance = v.maintenance; + this->build = v.build; + return *this; + } + VERSION setFromString (const std::wstring &str) + { + VERSION v = stringTo (str); + this->major = v.major; + this->minor = v.minor; + this->maintenance = v.maintenance; + this->build = v.build; + return *this; + } + private: + static std::vector splitVersionString (const std::string &str); + static std::vector splitVersionString (const std::wstring &str); +} _VERSION, VERSION, Version, version; +VERSION::VERSION (UINT16 major, UINT16 minor, UINT16 maintenance, UINT16 build): + major (major), minor (minor), maintenance (maintenance), build (build) {} +VERSION::VERSION (UINT64 verdata) : major ((verdata >> 0x30) & 0xFFFF), minor ((verdata >> 0x20) & 0xFFFF), +maintenance ((verdata >> 0x10) & 0xFFFF), build ((verdata) & 0xFFFF) {} +VERSION::VERSION (): major (0), minor (0), maintenance (0), build (0) {} +VERSION::~VERSION () +{ + this->major = 0; + this->minor = 0; + this->maintenance = 0; + this->build = 0; +} +std::wstring VERSION::toStringW () +{ + std::wstringstream ss; + ss << this->major << L'.' << this->minor << L'.' << this->maintenance << L'.' << this->build << std::ends; + std::wstring st (L""); + st += ss.str (); + return st; +} +std::string VERSION::toString () +{ + std::stringstream ss; + ss << this->major << '.' << this->minor << '.' << this->maintenance << '.' << this->build << std::ends; + std::string st (""); + st += ss.str (); + return st; +} +bool VERSION::isEmpty () +{ + return this->getUInt64 () == 0; +} +UINT64 VERSION::getUInt64 () +{ + UINT64 u64 = (((UINT64)major) << 0x30) | (((UINT64)minor) << 0x20) | (((UINT64)maintenance) << 0x10) | ((UINT64)build); + return u64; +} +INT64 VERSION::compare (VERSION &another) +{ + UINT64 u1 = this->getUInt64 (), u2 = another.getUInt64 (); + return u1 - u2; +} +bool VERSION::equals (VERSION &another) +{ + return !this->compare (another); +} +std::vector VERSION::splitVersionString (const std::string &str) +{ + std::vector result; + std::stringstream ss (str); + std::string segment; + while (std::getline (ss, segment, '.')) // Ȱ '.' + { + size_t pos = 0; + while ((pos = segment.find (',')) != std::string::npos) // ٰ ',' + { + result.push_back (segment.substr (0, pos)); + segment.erase (0, pos + 1); + } + result.push_back (segment); + } + return result; +} +std::vector VERSION::splitVersionString (const std::wstring &str) +{ + std::vector result; + std::wstringstream ss (str); + std::wstring segment; + while (std::getline (ss, segment, L'.')) // Ȱ '.' + { + size_t pos = 0; + while ((pos = segment.find (L',')) != std::wstring::npos) // ٰ ',' + { + result.push_back (segment.substr (0, pos)); + segment.erase (0, pos + 1); + } + result.push_back (segment); + } + return result; +} +VERSION VERSION::stringTo (const std::string &str) +{ + std::vector parts = splitVersionString (str); + UINT16 major = (parts.size () > 0) ? static_cast(std::stoi (parts [0])) : 0; + UINT16 minor = (parts.size () > 1) ? static_cast(std::stoi (parts [1])) : 0; + UINT16 maintenance = (parts.size () > 2) ? static_cast(std::stoi (parts [2])) : 0; + UINT16 build = (parts.size () > 3) ? static_cast(std::stoi (parts [3])) : 0; + return VERSION (major, minor, maintenance, build); +} +VERSION VERSION::stringTo (const std::wstring &str) +{ + std::vector parts = splitVersionString (str); + UINT16 major = (parts.size () > 0) ? static_cast(std::stoi (parts [0])) : 0; + UINT16 minor = (parts.size () > 1) ? static_cast(std::stoi (parts [1])) : 0; + UINT16 maintenance = (parts.size () > 2) ? static_cast(std::stoi (parts [2])) : 0; + UINT16 build = (parts.size () > 3) ? static_cast(std::stoi (parts [3])) : 0; + return VERSION (major, minor, maintenance, build); +} +VERSION VERSION::stringTo (LPCSTR str) +{ + return stringTo (std::string (str)); +} +VERSION VERSION::stringTo (LPCWSTR str) +{ + return stringTo (std::wstring (str)); +} +std::wstring GetPrerequistOSVersionText (VERSION &ver) +{ + if (ver >= VERSION (10, 0, 22621, 0)) return std::wstring (L"Windows 11 Version 22H2"); + else if (ver >= VERSION (10, 0, 22159, 0)) return std::wstring (L"Windows 11 Initial Release (Version 21H2)"); + else if (ver >= VERSION (10, 0, 19645, 0)) return std::wstring (L"Windows 10 Insider Preview (Build 19645)"); + else if (ver >= VERSION (10, 0, 19541, 0)) return std::wstring (L"Windows 10 Insider Preview (Build 19541)"); + else if (ver >= VERSION (10, 0, 19045, 0)) return std::wstring (L"Windows 10 Version 22H2"); + else if (ver >= VERSION (10, 0, 19044, 0)) return std::wstring (L"Windows 10 Version 21H2 (November 2021 Update)"); + else if (ver >= VERSION (10, 0, 19043, 0)) return std::wstring (L"Windows 10 Version 21H2 (May 2021 Update)"); + else if (ver >= VERSION (10, 0, 19042, 0)) return std::wstring (L"Windows 10 Version 20H2"); + else if (ver >= VERSION (10, 0, 18362, 0)) return std::wstring (L"Windows 10 May 2019 Update"); + else if (ver >= VERSION (10, 0, 17763, 0)) return std::wstring (L"Windows 10 October 2018 Update"); + else if (ver >= VERSION (10, 0, 17134, 0)) return std::wstring (L"Windows 10 April 2018 Update"); + else if (ver >= VERSION (10, 0, 16299, 0)) return std::wstring (L"Windows 10 Fall Creators Update"); + else if (ver >= VERSION (10, 0, 15063, 0)) return std::wstring (L"Windows 10 Creators Update"); + else if (ver >= VERSION (10, 0, 14393, 0)) return std::wstring (L"Windows 10 Anniversary Update"); + else if (ver >= VERSION (10, 0, 10240, 0)) return std::wstring (L"Windows 10"); + else if (ver >= VERSION (10, 0, 0, 0)) return std::wstring (L"Windows 10"); + else if (ver >= VERSION (6, 4, 9807, 0)) return std::wstring (L"Windows 10 Technical Preview"); + else if (ver >= VERSION (6, 3, 0, 0)) return std::wstring (L"Windows 8.1"); + else if (ver >= VERSION (6, 2, 0, 0)) return std::wstring (L"Windows 8"); + return std::wstring (L""); +} + +std::vector applicationItems = +{ + L"Id", + L"DisplayName", + L"BackgroundColor", + L"ForegroundText", + L"ShortName" +}; +typedef std::wstring strlabel, StringLabel; +std::wstring StringTrim (const std::wstring &str) +{ + if (str.empty ()) return L""; + LPCWSTR start = str.c_str (); + LPCWSTR end = start + str.size () - 1; +#define isblankstrlabelw(wch) (wch == L' ' || wch == L'\t' || wch == L'\n') + while (*start != L'\0' && isblankstrlabelw (*start)) ++start; + while (end >= start && isblankstrlabelw (*end)) --end; + if (start > end) return L""; + return std::wstring (start, end + 1); +} +std::string StringTrim (const std::string &str) +{ + if (str.empty ()) return ""; + LPCSTR start = str.c_str (); + LPCSTR end = start + str.size () - 1; +#define isblankstrlabela(wch) (wch == ' ' || wch == '\t' || wch == '\n') + while (*start != L'\0' && isblankstrlabela (*start)) ++start; + while (end >= start && isblankstrlabela (*end)) --end; + if (start > end) return ""; + return std::string (start, end + 1); +} +namespace l0km +{ + template < typename E, + typename TR = std::char_traits, + typename AL = std::allocator < E >> + 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 E, + typename TR = std::char_traits, + typename AL = std::allocator < E >> + 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; + } +} // namespace l0km +#define StringToUpper l0km::toupper +#define StringToLower l0km::tolower +int LabelCompare (const std::wstring &l1, const std::wstring &l2) +{ + std::wstring s1 = StringToUpper (StringTrim (l1)), + s2 = StringToUpper (StringTrim (l2)); + return lstrcmpW (s1.c_str (), s2.c_str ()); +} +int LabelCompare (LPCWSTR l1, LPCWSTR l2) +{ + return LabelCompare (std::wstring (l1), std::wstring (l2)); +} +int LabelCompare (const std::string &l1, const std::string &l2) +{ + std::string s1 = StringToUpper (StringTrim (l1)), + s2 = StringToUpper (StringTrim (l2)); + return lstrcmpA (s1.c_str (), s2.c_str ()); +} +int LabelCompare (LPCSTR l1, LPCSTR l2) +{ + return LabelCompare (std::string (l1), std::string (l2)); +} +bool LabelEqual (const std::wstring &l1, const std::wstring &l2) +{ + return !LabelCompare (l1, l2); +} +bool LabelEqual (LPCWSTR l1, LPCWSTR l2) +{ + return !LabelCompare (l1, l2); +} +bool LabelEqual (const std::string &l1, const std::string &l2) +{ + return !LabelCompare (l1, l2); +} +bool LabelEqual (LPCSTR l1, LPCSTR l2) +{ + return !LabelCompare (l1, l2); +} + +typedef class ApplicationMap: public std::map +{ + public: + std::wstring getAppUserModelID (); + friend bool operator == (ApplicationMap &a1, ApplicationMap &a2) + { + const LPWSTR lpKey = L"AppUserModelID"; + std::wstring wKey (lpKey); + if (a1.find (wKey) == a1.end () && a2.find (wKey) == a2.end ()) return true; + else if (a1.find (wKey) != a1.end () && a2.find (wKey) != a2.end ()) + { + return a1 [wKey] == a2 [wKey]; + } + else return false; + } + friend bool operator != (ApplicationMap &a1, ApplicationMap &a2) + { + return !(a1 == a2); + } +} appmap; +std::wstring ApplicationMap::getAppUserModelID () +{ + if (this->find (L"AppUserModelID") == this->end ()) return std::wstring (L""); + else return (*this) [std::wstring (L"AppUserModelID")]; +} + +class DEPINFO +{ + public: + std::wstring name; + std::wstring publisher; + VERSION versionMin; + DEPINFO (LPWSTR name, LPWSTR publisher, UINT64 versionLimit); + DEPINFO (IAppxManifestPackageDependency *dependency); + DEPINFO (); + bool operator == (DEPINFO &another) { return this->name == another.name; } + bool isEmpty () { return name.length () == 0; } +}; +DEPINFO::DEPINFO (LPWSTR name, LPWSTR publisher, UINT64 versionLimit): + name (name), publisher (publisher), versionMin (*((VERSION *)&versionLimit)) +{ +} +DEPINFO::DEPINFO (IAppxManifestPackageDependency *dependency) +{ + LPWSTR deName = NULL; + LPWSTR dePub = NULL; + UINT64 deMinVer; + dependency->GetName (&deName); + dependency->GetPublisher (&dePub); + dependency->GetMinVersion (&deMinVer); + name = std::wstring (L""); + publisher = std::wstring (L""); + if (deName) name += deName; + if (dePub) publisher += dePub; + versionMin = VERSION (deMinVer); + if (deName) CoTaskMemFree (deName); + if (dePub) CoTaskMemFree (dePub); +} +DEPINFO::DEPINFO (): name (L""), publisher (L""), versionMin (0) {} + +class AppxReader +{ + private: + std::wstring m_filePath = L""; + IAPPXREADER m_appxReader = NULL; + public: + // ÿһεĴٴԴʧ֮ǰɹҲᱻ١ + AppxReader (LPCWSTR swFilePath); + AppxReader (const std::wstring swFilePath); + AppxReader (IStream *objcomFile); + AppxReader (IAppxFile *objcomFile); + AppxReader (); + ~AppxReader (); + bool create (LPCWSTR swFilePath); + bool create (const std::wstring &objswFile); + bool create (IStream *objcomFile); + bool create (IAppxFile *objAppxFile); + // ע⣺ִٲʱĶȡҲ٣˷ǺΣյIJ + bool create (IAppxPackageReader *objAppxReader); + bool destroy (); + // ڴ˶ȡļΪҪȡҪжļǷãʹôˡ + bool isFileExists (); + // ж϶ȡǷãǷļʽ򿪡 + bool isAvailable (); + // ļ򿪵Ķȡ + bool isFileReaderAvailable (); + // ֶͷţָŴ˶ٶͷ + const IAPPXREADER getPackageReader () const { return this->m_appxReader; } + // ֶͷţָŴ˶ٶͷ + LPCWSTR getFilePath (); + IAppxManifestReader *getManifest (); + IAppxManifestPackageId *getIdentity (); + std::wstring getIdentityName (); + std::wstring getIdentityPublisher (); + VERSION getIdentityVersion (); + size_t getIdentityProcessorArchitecture (std::vector &arrOut); + size_t getResourceLanguages (std::vector &vec); + IAppxManifestProperties *getProperties (); + std::wstring getPropertiesStringValue (LPCWSTR lpswName); + std::wstring getPropertiesStringValue (const std::wstring objswName); + HRESULT getPropertiesBoolValue (LPCWSTR lpswName, BOOL &bOutput); + HRESULT getPropertiesBoolValue (const std::wstring objswName, BOOL &bOutput); + std::wstring getPropertyName (); + std::wstring getPropertyDescription (); + std::wstring getPropertyPublisher (); + std::wstring getPropertyLogo (); + UINT64 getPrerequisite (LPCWSTR lpswName); + UINT64 getPrerequisite (const std::wstring objswName); + VERSION getPrerequisiteOSMinVersion (); + IAppxManifestApplicationsEnumerator *getApplicationsEnumerator (); + bool isPackageApplication (); + size_t getApplications (std::vector &output); + size_t getApplicationUserModelIDs (std::vector &output); + size_t getApplicationIDs (std::vector &output); + size_t getApplicationVisualElementsBackgroundColor (std::vector &output); + APPX_CAPABILITIES getCapabilitiesFlag (); + size_t getDeviceCapabilities (std::vector &output); + // getCapabilitiesFlag getDeviceCapabilities + size_t getCapabilities (std::vector &output); + IAppxManifestPackageDependenciesEnumerator *getDependenciesEnumerator (); + size_t getDependencies (std::vector &output); + IStream *getPriFileStream (); + IStream *extractFileToStream (LPCWSTR lpswFilePath); + IStream *extractFileToStream (std::wstring objswFilePath); +}; +AppxReader::AppxReader (LPCWSTR swFilePath) { this->create (swFilePath); } +AppxReader::AppxReader (std::wstring swFilePath) { this->create (swFilePath); } +AppxReader::AppxReader (): m_appxReader (NULL), m_filePath (L"") {} +AppxReader::AppxReader (IStream *objcomFile) : m_filePath (L"") +{ + this->create (objcomFile); +} +AppxReader::AppxReader (IAppxFile *objcomFile) : m_filePath (L"") +{ + this->create (objcomFile); +} +AppxReader::~AppxReader () { this->destroy (); } +bool AppxReader::isFileExists () +{ + return !this->m_filePath.empty () && this->m_filePath.length () > 0 && IsFileExists (this->m_filePath); +} +bool AppxReader::isAvailable () +{ + return this->m_appxReader != NULL; +} +bool AppxReader::isFileReaderAvailable () +{ + return this->isFileExists () && this->isAvailable (); +} +bool AppxReader::destroy () +{ + if (!this->isAvailable ()) return false; // ʾٵ + this->m_appxReader->Release (); + this->m_appxReader = NULL; + this->m_filePath = std::wstring (L""); + return true; +} +bool AppxReader::create (LPCWSTR swFilePath) +{ + this->destroy (); + if (!swFilePath) return false; + if (!lstrlenW (swFilePath)) return false; + if (!IsFileExists (swFilePath)) return false; + HRESULT hr = GetPackageReader (swFilePath, &this->m_appxReader); + if (FAILED (hr)) + { + if (this->m_appxReader) this->m_appxReader->Release (); + this->m_appxReader = NULL; + return false; + } + if (!this->m_appxReader) return false; + this->m_filePath = L""; + this->m_filePath += std::wstring (swFilePath); + return this->isAvailable (); +} +bool AppxReader::create (const std::wstring &objswFile) { return this->create (objswFile.c_str ()); } +bool AppxReader::create (IStream *objcomFile) +{ + this->destroy (); + if (!objcomFile) return false; + HRESULT hr = GetAppxPackageReader (objcomFile, &this->m_appxReader); + if (!this->m_appxReader) return false; + if (FAILED (hr)) + { + if (this->m_appxReader) this->m_appxReader->Release (); + this->m_appxReader = NULL; + return false; + } + return true; +} +bool AppxReader::create (IAppxFile *objAppxFile) +{ + this->destroy (); + IStream *ifile = NULL; + if (!objAppxFile) return false; + HRESULT hr = objAppxFile->GetStream (&ifile); + if (FAILED (hr)) + { + if (ifile) ifile->Release (); + return false; + } + return this->create (ifile); +} +bool AppxReader::create (IAppxPackageReader *objAppxReader) +{ + this->destroy (); + if (!objAppxReader) return false; + this->m_appxReader = objAppxReader; + return objAppxReader != NULL; +} +LPCWSTR AppxReader::getFilePath () { return this->m_filePath.c_str (); } +IAppxManifestReader *AppxReader::getManifest () +{ + if (!this->isAvailable ()) return NULL; + IAppxManifestReader *manifest = NULL; + HRESULT hr = this->m_appxReader->GetManifest (&manifest); + if (!manifest) return NULL; + if (FAILED (hr)) + { + if (manifest) manifest->Release (); + return NULL; + } + return manifest; +} +IAppxManifestPackageId *AppxReader::getIdentity () +{ + if (!this->isAvailable ()) return NULL; + IAppxManifestReader *manifest = this->getManifest (); + if (!manifest) return NULL; + IAppxManifestPackageId *packageId = NULL; + HRESULT hr = manifest->GetPackageId (&packageId); + if (manifest) { manifest->Release (); manifest = NULL; } + if (!packageId) return NULL; + if (FAILED (hr)) + { + if (packageId) packageId->Release (); + return NULL; + } + return packageId; +} +std::wstring AppxReader::getIdentityName () +{ + std::wstring temp (L""); + IAppxManifestPackageId *packageId = this->getIdentity (); + if (!packageId) return temp; + LPWSTR lpwzName = NULL; + HRESULT hr = packageId->GetName (&lpwzName); + if (FAILED (hr)) + { + if (lpwzName) CoTaskMemFree (lpwzName); + packageId->Release (); + return temp; + } + if (lpwzName) temp += lpwzName; + if (lpwzName) CoTaskMemFree (lpwzName); + packageId->Release (); + return temp; +} +std::wstring AppxReader::getIdentityPublisher () +{ + std::wstring temp (L""); + IAppxManifestPackageId *packageId = this->getIdentity (); + if (!packageId) return temp; + LPWSTR lpwzName = NULL; + HRESULT hr = packageId->GetPublisher (&lpwzName); + if (FAILED (hr)) + { + if (lpwzName) CoTaskMemFree (lpwzName); + packageId->Release (); + return temp; + } + if (lpwzName) temp += lpwzName; + if (lpwzName) CoTaskMemFree (lpwzName); + packageId->Release (); + return temp; +} +VERSION AppxReader::getIdentityVersion () +{ + VERSION temp (0); + IAppxManifestPackageId *packageId = this->getIdentity (); + if (!packageId) return temp; + UINT64 u64 = 0; + HRESULT hr = packageId->GetVersion (&u64); + temp = VERSION (u64); + packageId->Release (); + return temp; +} +size_t AppxReader::getIdentityProcessorArchitecture (std::vector &arrOut) +{ + if (!&arrOut) return 0; + arrOut.clear (); + IAppxManifestPackageId *packageId = this->getIdentity (); + if (!packageId) return 0; + APPX_PACKAGE_ARCHITECTURE apa = APPX_PACKAGE_ARCHITECTURE_NEUTRAL; + packageId->GetArchitecture (&apa); + push_no_repeat (arrOut, apa); + return arrOut.size (); +} +size_t AppxReader::getResourceLanguages (std::vector &vec) +{ + if (!&vec) return 0; + vec.clear (); + CComPtr manifest = NULL; + HRESULT hr = this->m_appxReader->GetManifest (&manifest); + if (FAILED (hr)) return 0; + CComPtr manifest2 = NULL; + hr = manifest->QueryInterface (__uuidof(IAppxManifestReader2), (void**)&manifest2); + if (FAILED (hr)) return 0; + CComPtr qres = NULL; + hr = manifest2->GetQualifiedResources (&qres); + if (FAILED (hr)) return 0; + BOOL hasCurrent = FALSE; + hr = qres->GetHasCurrent (&hasCurrent); + while (SUCCEEDED (hr) && hasCurrent) + { + CComPtr res = NULL; + hr = qres->GetCurrent (&res); + if (FAILED (hr)) goto Loop_MoveNext; + LPWSTR lpswLCode = NULL; + hr = res->GetLanguage (&lpswLCode); + if (FAILED (hr)) goto Loop_MoveNext; + if (lpswLCode && lstrlenW (lpswLCode) > 0) + { + std::wstring tempStr (lpswLCode), tempLowerStr; + tempLowerStr = StringToLower (tempStr); + push_no_repeat (vec, lpswLCode); + } + Loop_MoveNext: + hr = qres->MoveNext (&hasCurrent); + } + return vec.size (); +} +IAppxManifestProperties *AppxReader::getProperties () +{ + IAppxManifestReader *manifest = this->getManifest (); + if (!manifest) return NULL; + IAppxManifestProperties *properties = NULL; + HRESULT hr = manifest->GetProperties (&properties); + if (manifest) { manifest->Release (); manifest = NULL; } + if (!properties) return NULL; + if (FAILED (hr)) { if (properties) properties->Release (); return NULL; } + return properties; +} +std::wstring AppxReader::getPropertiesStringValue (LPCWSTR lpswName) +{ + std::wstring temp (L""); + if (!lpswName) return NULL; + IAppxManifestProperties *properties = this->getProperties (); + if (!properties) return temp; + LPWSTR lpswValue = NULL; + HRESULT hr = properties->GetStringValue (lpswName, &lpswValue); + properties->Release (); + if (lpswValue) { temp += lpswValue; CoTaskMemFree (lpswValue); lpswValue = NULL; } + return temp; +} +std::wstring AppxReader::getPropertiesStringValue (const std::wstring objswName) +{ + return this->getPropertiesStringValue (objswName.c_str ()); +} +HRESULT AppxReader::getPropertiesBoolValue (LPCWSTR lpswName, BOOL &bOutput) +{ + HRESULT hr = E_FAIL; + if (!lpswName || !&bOutput) return hr; + IAppxManifestProperties *properties = this->getProperties (); + if (!properties) return hr; + hr = properties->GetBoolValue (lpswName, &bOutput); + properties->Release (); + return hr; +} +HRESULT AppxReader::getPropertiesBoolValue (const std::wstring objswName, BOOL &bOutput) +{ + return this->getPropertiesBoolValue (objswName.c_str (), bOutput); +} +std::wstring AppxReader::getPropertyName () +{ + return this->getPropertiesStringValue (L"DisplayName"); +} +std::wstring AppxReader::getPropertyDescription () +{ + return this->getPropertiesStringValue (L"Description"); +} +std::wstring AppxReader::getPropertyPublisher () +{ + return this->getPropertiesStringValue (L"PublisherDisplayName"); +} +std::wstring AppxReader::getPropertyLogo () +{ + return this->getPropertiesStringValue (L"Logo"); +} +// ʧܷ NULL +UINT64 AppxReader::getPrerequisite (LPCWSTR lpswName) +{ + IAppxManifestReader *manifest = this->getManifest (); + if (!manifest) return NULL; + UINT64 u64t = 0; + HRESULT hr = manifest->GetPrerequisite (lpswName, &u64t); + if (manifest) manifest->Release (); + if (FAILED (hr)) return NULL; + return u64t; +} +// ʧܷ NULL +UINT64 AppxReader::getPrerequisite (const std::wstring objswName) +{ + return this->getPrerequisite (objswName.c_str ()); +} +VERSION AppxReader::getPrerequisiteOSMinVersion () +{ + UINT64 temp = this->getPrerequisite (L"OSMinVersion"); + return VERSION (temp); +} +IAppxManifestApplicationsEnumerator *AppxReader::getApplicationsEnumerator () +{ + IAppxManifestReader *manifest = this->getManifest (); + if (!manifest) return NULL; + IAppxManifestApplicationsEnumerator *temp = NULL; + HRESULT hr = manifest->GetApplications (&temp); + manifest->Release (); + if (!temp) return NULL; + if (FAILED (hr)) { if (temp) temp->Release (); return NULL; } + return temp; +} +bool AppxReader::isPackageApplication () +{ + IAppxManifestApplicationsEnumerator *aenum = this->getApplicationsEnumerator (); + if (!aenum) return false; + BOOL hasCurrent = FALSE; + HRESULT hr = aenum->GetHasCurrent (&hasCurrent); + aenum->Release (); + return SUCCEEDED (hr) && hasCurrent; +} +size_t AppxReader::getApplications (std::vector &output) +{ + if (!&output) return false; + output.clear (); + CComPtr aenum = this->getApplicationsEnumerator (); + if (!aenum) return 0; + BOOL hasCurrent = FALSE; + HRESULT hr = aenum->GetHasCurrent (&hasCurrent); + while (SUCCEEDED (hr) && hasCurrent) + { + CComPtr app = NULL; + hr = aenum->GetCurrent (&app); + if (SUCCEEDED (hr)) + { + appmap map; + LPWSTR lpswTemp = NULL; + hr = app->GetAppUserModelId (&lpswTemp); + if (!lpswTemp) { hr = aenum->MoveNext (&hasCurrent); continue; } + if (SUCCEEDED (hr)) + { + { + std::wstring objT (L""); + if (lpswTemp) objT += lpswTemp; + if (objT.length () <= 0) + { + if (lpswTemp) CoTaskMemFree (lpswTemp); + lpswTemp = NULL; + hr = aenum->MoveNext (&hasCurrent); + continue; + } + map [StringLabel (L"AppUserModelID")] = objT; + } + for (auto it : applicationItems) + { + LPWSTR lpswTemp2 = NULL; + hr = app->GetStringValue (it.c_str (), &lpswTemp2); + if (FAILED (hr) || !lpswTemp2) + { + if (lpswTemp2) CoTaskMemFree (lpswTemp2); + continue; + } + if (lstrlenW (lpswTemp2) <= 0) + { + if (lpswTemp2) CoTaskMemFree (lpswTemp2); + continue; + } + std::wstring objT (L""); + if (lpswTemp2) objT += lpswTemp2; + map [StringLabel (it)] = objT; + } + push_no_repeat (output, map); + } + if (!lpswTemp) CoTaskMemFree (lpswTemp); + } + hr = aenum->MoveNext (&hasCurrent); + } + return output.size (); +} +size_t AppxReader::getApplicationUserModelIDs (std::vector &output) +{ + if (!&output) return 0; + output.clear (); + std::vector maps; + this->getApplications (maps); + for (auto it : maps) + { + std::wstring t (L""); + t += it.getAppUserModelID (); + push_no_repeat (output, t); + } + return output.size (); +} +size_t AppxReader::getApplicationIDs (std::vector &output) +{ + if (!&output) return 0; + output.clear (); + std::vector maps; + this->getApplications (maps); + for (auto it : maps) + { + std::wstring t (L""); + t += it [StringLabel (L"Id")]; + push_no_repeat (output, t); + } + return output.size (); +} +size_t AppxReader::getApplicationVisualElementsBackgroundColor (std::vector &output) +{ + if (!&output) return 0; + output.clear (); + std::vector maps; + this->getApplications (maps); + for (auto it : maps) + { + std::wstring t (L""); + t += it [StringLabel (L"BackgroundColor")]; + push_no_repeat (output, t); + } + return output.size (); +} +APPX_CAPABILITIES AppxReader::getCapabilitiesFlag () +{ + CComPtr manifest = this->getManifest (); + if (!manifest) return (APPX_CAPABILITIES)NULL; + APPX_CAPABILITIES temp; + HRESULT hr = manifest->GetCapabilities (&temp); + if (FAILED (hr)) return (APPX_CAPABILITIES)NULL; + return temp; +} +size_t AppxReader::getDeviceCapabilities (std::vector &output) +{ + if (!&output) return 0; + output.clear (); + CComPtr manifest = this->getManifest (); + if (!manifest) return 0; + CComPtr denum = NULL; + HRESULT hr = manifest->GetDeviceCapabilities (&denum); + if (!denum) return 0; + if (FAILED (hr)) return 0; + BOOL hasCurrent = FALSE; + hr = denum->GetHasCurrent (&hasCurrent); + while (SUCCEEDED (hr) && hasCurrent) + { + LPWSTR lpswT = NULL; + hr = denum->GetCurrent (&lpswT); + if (lpswT) + { + if (SUCCEEDED (hr)) + { + std::wstring objswT (L""); + if (lpswT) objswT += lpswT; + if (objswT.length () > 0) push_no_repeat (output, objswT); + if (lpswT) CoTaskMemFree (lpswT); + } + } + hr = denum->MoveNext (&hasCurrent); + } + return output.size (); +} +size_t AppxReader::getCapabilities (std::vector &output) +{ + if (!&output) return 0; + output.clear (); + std::vector dcap; + GetCapabilitiesName (this->getCapabilitiesFlag (), output); + this->getDeviceCapabilities (dcap); + for (auto it : dcap) + { + std::wstring temp (L""); + temp += it; + push_no_repeat (output, temp); + } + return output.size (); +} +IAppxManifestPackageDependenciesEnumerator *AppxReader::getDependenciesEnumerator () +{ + CComPtr manifest = this->getManifest (); + if (!manifest) return NULL; + IAppxManifestPackageDependenciesEnumerator *deps; + HRESULT hr = manifest->GetPackageDependencies (&deps); + if (!deps) return NULL; + if (FAILED (hr)) + { + if (deps) deps->Release (); + return NULL; + } + return deps; +} +size_t AppxReader::getDependencies (std::vector &output) +{ + if (!&output) return 0; + output.clear (); + CComPtr deps = this->getDependenciesEnumerator (); + if (!deps) return 0; + BOOL hasCurrent = FALSE; + HRESULT hr = deps->GetHasCurrent (&hasCurrent); + while (SUCCEEDED (hr) && hasCurrent) + { + CComPtr dep = NULL; + hr = deps->GetCurrent (&dep); + if (SUCCEEDED (hr)) + { + DEPINFO dinfo (dep); + push_no_repeat (output, dinfo); + } + hr = deps->MoveNext (&hasCurrent); + } + return output.size (); +} +IStream *AppxReader::extractFileToStream (LPCWSTR lpswFilePath) +{ + if (!lpswFilePath) return false; + if (lstrlenW (lpswFilePath) <= 0) return false; + CComPtr ifile = NULL; + HRESULT hr = this->m_appxReader->GetPayloadFile (lpswFilePath, &ifile); + if (!ifile) return NULL; + if (FAILED (hr)) return NULL; + IStream *sfile = NULL; + hr = ifile->GetStream (&sfile); + if (!sfile) return NULL; + if (FAILED (hr)) return NULL; + return sfile; +} +IStream *AppxReader::extractFileToStream (std::wstring objswFilePath) +{ + return this->extractFileToStream (objswFilePath.c_str ()); +} +IStream *AppxReader::getPriFileStream () +{ + return this->extractFileToStream (L"resources.pri"); +} + +class BundleReader +{ + private: + std::wstring m_filePath = L""; + IBUNDLEREADER m_bundleReader = NULL; + public: + // ÿһεĴٴԴʧ֮ǰɹҲᱻ١ + BundleReader (LPCWSTR swFilePath); + BundleReader (const std::wstring swFilePath); + BundleReader (); + ~BundleReader (); + bool create (LPCWSTR swFilePath); + bool create (const std::wstring &objswFile); + // ע⣺ִٲʱĶȡҲ٣˷ǺΣյIJ + bool destroy (); + // ڴ˶ȡļΪҪȡҪжļǷãʹôˡ + bool isFileExists (); + // ж϶ȡǷãǷļʽ򿪡 + bool isAvailable (); + // ļ򿪵Ķȡ + bool isFileReaderAvailable (); + // ֶͷţָŴ˶ٶͷ + const IBUNDLEREADER getPackageReader () const { return this->m_bundleReader; } + // ֶͷ + IAPPXREADER getAppxPackageReader (); + // ֶͷţָŴ˶ٶͷ + LPCWSTR getFilePath (); + IAppxBundleManifestReader *getManifest (); + // ȡӰ嵥ΪӦðΪԴ/ + IAppxManifestReader *getAppxManifest (); + IAppxManifestPackageId *getIdentity (); + IAppxManifestPackageId *getAppxIdentity (); + std::wstring getIdentityName (); + std::wstring getIdentityPublisher (); + VERSION getIdentityVersion (); + size_t getIdentityProcessorArchitecture (std::vector &arrOut); + size_t getResourceLanguages (std::vector &vec); + IAppxManifestProperties *getProperties (); + std::wstring getPropertiesStringValue (LPCWSTR lpswName); + std::wstring getPropertiesStringValue (const std::wstring objswName); + HRESULT getPropertiesBoolValue (LPCWSTR lpswName, BOOL &bOutput); + HRESULT getPropertiesBoolValue (const std::wstring objswName, BOOL &bOutput); + std::wstring getPropertyName (); + std::wstring getPropertyDescription (); + std::wstring getPropertyPublisher (); + std::wstring getPropertyLogo (); + UINT64 getPrerequisite (LPCWSTR lpswName); + UINT64 getPrerequisite (const std::wstring objswName); + VERSION getPrerequisiteOSMinVersion (); + IAppxManifestApplicationsEnumerator *getApplicationsEnumerator (); + bool isPackageApplication (); + size_t getApplications (std::vector &output); + size_t getApplicationUserModelIDs (std::vector &output); + size_t getApplicationIDs (std::vector &output); + size_t getApplicationVisualElementsBackgroundColor (std::vector &output); + APPX_CAPABILITIES getCapabilitiesFlag (); + size_t getDeviceCapabilities (std::vector &output); + // getCapabilitiesFlag getDeviceCapabilities + size_t getCapabilities (std::vector &output); + IAppxManifestPackageDependenciesEnumerator *getDependenciesEnumerator (); + size_t getDependencies (std::vector &output); + IStream *getPriFileStream (); + IStream *extractFileToStream (LPCWSTR lpswFilePath); + IStream *extractFileToStream (std::wstring objswFilePath); +}; +BundleReader::BundleReader (LPCWSTR swFilePath) { this->create (swFilePath); } +BundleReader::BundleReader (const std::wstring swFilePath) { this->create (swFilePath); } +BundleReader::BundleReader (): m_filePath (L""), m_bundleReader (NULL) {} +BundleReader::~BundleReader () { this->destroy (); } +bool BundleReader::isFileExists () +{ + return !this->m_filePath.empty () && this->m_filePath.length () > 0 && IsFileExists (this->m_filePath); +} +bool BundleReader::isAvailable () +{ + return this->m_bundleReader != NULL; +} +bool BundleReader::isFileReaderAvailable () +{ + return this->isFileExists () && this->isAvailable (); +} +bool BundleReader::destroy () +{ + if (!this->isAvailable ()) return false; // ʾٵ + this->m_bundleReader->Release (); + this->m_bundleReader = NULL; + this->m_filePath = std::wstring (L""); + return true; +} +bool BundleReader::create (LPCWSTR swFilePath) +{ + this->destroy (); + if (!swFilePath) return false; + if (!lstrlenW (swFilePath)) return false; + if (!IsFileExists (swFilePath)) return false; + HRESULT hr = GetBundleReader (swFilePath, &this->m_bundleReader); + if (FAILED (hr)) + { + if (this->m_bundleReader) this->m_bundleReader->Release (); + this->m_bundleReader = NULL; + return false; + } + if (!this->m_bundleReader) return false; + this->m_filePath = L""; + this->m_filePath += std::wstring (swFilePath); + return this->isAvailable (); +} +bool BundleReader::create (const std::wstring &objswFile) { return this->create (objswFile.c_str ()); } +LPCWSTR BundleReader::getFilePath () { return this->m_filePath.c_str (); } +IAppxBundleManifestReader *BundleReader::getManifest () +{ + if (!this->isAvailable ()) return NULL; + IAppxBundleManifestReader *bmanifest = NULL; + HRESULT hr = this->m_bundleReader->GetManifest (&bmanifest); + if (!bmanifest) return NULL; + if (FAILED (hr)) + { + if (bmanifest) bmanifest->Release (); + return NULL; + } + return bmanifest; +} +IAPPXREADER BundleReader::getAppxPackageReader () +{ + CComPtr bmanifest = this->getManifest (); + if (!bmanifest) return NULL; + CComPtr pienum = NULL; + HRESULT hr = bmanifest->GetPackageInfoItems (&pienum); + if (!pienum || FAILED (hr)) return NULL; + BOOL hasCurrent = FALSE; + hr = pienum->GetHasCurrent (&hasCurrent); + while (SUCCEEDED (hr) && hasCurrent) + { + CComPtr pinfo = NULL; + hr = pienum->GetCurrent (&pinfo); + if (pinfo && SUCCEEDED (hr)) + { + APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE ftype = APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE_RESOURCE; + hr = pinfo->GetPackageType (&ftype); + if (SUCCEEDED (hr) && ftype == APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE_APPLICATION) + { + LPWSTR lpswSubPkgName = NULL; + hr = pinfo->GetFileName (&lpswSubPkgName); + if (lpswSubPkgName && SUCCEEDED (hr)) + { + CComPtr ifile = NULL; + hr = this->m_bundleReader->GetPayloadPackage (lpswSubPkgName, &ifile); + CoTaskMemFree (lpswSubPkgName); + if (ifile && SUCCEEDED (hr)) + { + CComPtr isfile = NULL; + hr = ifile->GetStream (&isfile); + if (SUCCEEDED (hr) && isfile) + { + IAPPXREADER areader = NULL; + hr = GetAppxPackageReader (isfile, &areader); + if (FAILED (hr)) + { + if (areader) areader->Release (); + return NULL; + } + return areader; + } + } + } + } + } + hr = pienum->MoveNext (&hasCurrent); + } + hr = pienum->GetHasCurrent (&hasCurrent); + while (SUCCEEDED (hr) && hasCurrent) + { + CComPtr pinfo = NULL; + hr = pienum->GetCurrent (&pinfo); + if (pinfo && SUCCEEDED (hr)) + { + LPWSTR lpswSubPkgName = NULL; + hr = pinfo->GetFileName (&lpswSubPkgName); + if (lpswSubPkgName && SUCCEEDED (hr)) + { + CComPtr ifile = NULL; + hr = this->m_bundleReader->GetPayloadPackage (lpswSubPkgName, &ifile); + CoTaskMemFree (lpswSubPkgName); + if (ifile && SUCCEEDED (hr)) + { + CComPtr isfile = NULL; + hr = ifile->GetStream (&isfile); + if (SUCCEEDED (hr) && isfile) + { + IAPPXREADER areader = NULL; + hr = GetAppxPackageReader (isfile, &areader); + if (FAILED (hr)) + { + if (areader) areader->Release (); + return NULL; + } + return areader; + } + } + } + } + hr = pienum->MoveNext (&hasCurrent); + } + return NULL; +} +IAppxManifestReader* BundleReader::getAppxManifest () +{ + CComPtr bmanifest = this->getManifest (); + if (!bmanifest) return NULL; + CComPtr pienum = NULL; + HRESULT hr = bmanifest->GetPackageInfoItems (&pienum); + if (!pienum || FAILED (hr)) return NULL; + BOOL hasCurrent = FALSE; + hr = pienum->GetHasCurrent (&hasCurrent); + while (SUCCEEDED (hr) && hasCurrent) + { + CComPtr pinfo = NULL; + hr = pienum->GetCurrent (&pinfo); + if (pinfo && SUCCEEDED (hr)) + { + APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE ftype = APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE_RESOURCE; + hr = pinfo->GetPackageType (&ftype); + if (SUCCEEDED (hr) && ftype == APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE_APPLICATION) + { + LPWSTR lpswSubPkgName = NULL; + hr = pinfo->GetFileName (&lpswSubPkgName); + if (lpswSubPkgName && SUCCEEDED (hr)) + { + CComPtr ifile = NULL; + hr = this->m_bundleReader->GetPayloadPackage (lpswSubPkgName, &ifile); + CoTaskMemFree (lpswSubPkgName); + if (ifile && SUCCEEDED (hr)) + { + AppxReader areader (ifile); + IAppxManifestReader* amanifest = areader.getManifest (); + if (amanifest) return amanifest; + } + } + } + } + hr = pienum->MoveNext (&hasCurrent); + } + hr = pienum->GetHasCurrent (&hasCurrent); + while (SUCCEEDED (hr) && hasCurrent) + { + CComPtr pinfo = NULL; + hr = pienum->GetCurrent (&pinfo); + if (pinfo && SUCCEEDED (hr)) + { + LPWSTR lpswSubPkgName = NULL; + hr = pinfo->GetFileName (&lpswSubPkgName); + if (lpswSubPkgName && SUCCEEDED (hr)) + { + CComPtr ifile = NULL; + hr = this->m_bundleReader->GetPayloadPackage (lpswSubPkgName, &ifile); + CoTaskMemFree (lpswSubPkgName); + if (ifile && SUCCEEDED (hr)) + { + AppxReader areader (ifile); + IAppxManifestReader* amanifest = areader.getManifest (); + if (amanifest) return amanifest; + } + } + } + hr = pienum->MoveNext (&hasCurrent); + } + return NULL; +} +IAppxManifestPackageId *BundleReader::getIdentity () +{ + CComPtr bmanifest = this->getManifest (); + if (!bmanifest) return NULL; + IAppxManifestPackageId *packageId = NULL; + HRESULT hr = bmanifest->GetPackageId (&packageId); + if (!packageId) return NULL; + if (FAILED (hr)) + { + packageId->Release (); + return NULL; + } + return packageId; +} +IAppxManifestPackageId *BundleReader::getAppxIdentity () +{ + CComPtr amanifest = this->getAppxManifest (); + if (!amanifest) return NULL; + IAppxManifestPackageId *packageId = NULL; + HRESULT hr = amanifest->GetPackageId (&packageId); + if (!packageId) return NULL; + if (FAILED (hr)) + { + packageId->Release (); + return NULL; + } + return packageId; +} +std::wstring BundleReader::getIdentityName () +{ + std::wstring t (L""); + CComPtr packageId = this->getAppxIdentity (); + if (!packageId) packageId = this->getIdentity (); + if (!packageId) return t; + LPWSTR lpswT = NULL; + HRESULT hr = packageId->GetName (&lpswT); + if (!lpswT) return t; + if (FAILED (hr)) { if (lpswT) CoTaskMemFree (lpswT); return t; } + if (lpswT) t += lpswT; + if (lpswT) CoTaskMemFree (lpswT); + return t; +} +std::wstring BundleReader::getIdentityPublisher () +{ + std::wstring t (L""); + CComPtr packageId = this->getAppxIdentity (); + if (!packageId) packageId = this->getIdentity (); + if (!packageId) return t; + LPWSTR lpswT = NULL; + HRESULT hr = packageId->GetPublisher (&lpswT); + if (!lpswT) return t; + if (FAILED (hr)) { if (lpswT) CoTaskMemFree (lpswT); return t; } + if (lpswT) t += lpswT; + if (lpswT) CoTaskMemFree (lpswT); + return t; +} +VERSION BundleReader::getIdentityVersion () +{ + VERSION v (0); + CComPtr packageId = this->getAppxIdentity (); + if (!packageId) packageId = this->getIdentity (); + if (!packageId) return v; + UINT64 u64 = 0; + HRESULT hr = packageId->GetVersion (&u64); + v = VERSION (u64); + return v; +} +size_t BundleReader::getIdentityProcessorArchitecture (std::vector &arrOut) +{ + CComPtr bmanifest = this->getManifest (); + if (!bmanifest) return 0; + CComPtr pienum = NULL; + HRESULT hr = bmanifest->GetPackageInfoItems (&pienum); + if (!pienum || FAILED (hr)) return 0; + BOOL hasCurrent = FALSE; + hr = pienum->GetHasCurrent (&hasCurrent); + while (SUCCEEDED (hr) && hasCurrent) + { + CComPtr pinfo = NULL; + hr = pienum->GetCurrent (&pinfo); + if (pinfo && SUCCEEDED (hr)) + { + APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE ftype = APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE_RESOURCE; + hr = pinfo->GetPackageType (&ftype); + if (SUCCEEDED (hr) && ftype == APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE_APPLICATION) + { + LPWSTR lpswSubPkgName = NULL; + hr = pinfo->GetFileName (&lpswSubPkgName); + if (lpswSubPkgName && SUCCEEDED (hr)) + { + CComPtr ifile = NULL; + hr = this->m_bundleReader->GetPayloadPackage (lpswSubPkgName, &ifile); + CoTaskMemFree (lpswSubPkgName); + if (ifile && SUCCEEDED (hr)) + { + AppxReader areader (ifile); + std::vector tarr; + areader.getIdentityProcessorArchitecture (tarr); + for (auto it : tarr) push_no_repeat (arrOut, it); + } + } + } + } + hr = pienum->MoveNext (&hasCurrent); + } + return arrOut.size (); +} +size_t BundleReader::getResourceLanguages (std::vector &vec) +{ + CComPtr bmanifest = this->getManifest (); + if (!bmanifest) return 0; + CComPtr pienum = NULL; + HRESULT hr = bmanifest->GetPackageInfoItems (&pienum); + if (!pienum || FAILED (hr)) return 0; + BOOL hasCurrent = FALSE; + hr = pienum->GetHasCurrent (&hasCurrent); + while (SUCCEEDED (hr) && hasCurrent) + { + CComPtr pinfo = NULL; + hr = pienum->GetCurrent (&pinfo); + if (pinfo && SUCCEEDED (hr)) + { + LPWSTR lpswSubPkgName = NULL; + hr = pinfo->GetFileName (&lpswSubPkgName); + if (lpswSubPkgName && SUCCEEDED (hr)) + { + CComPtr ifile = NULL; + hr = this->m_bundleReader->GetPayloadPackage (lpswSubPkgName, &ifile); + CoTaskMemFree (lpswSubPkgName); + if (ifile && SUCCEEDED (hr)) + { + AppxReader areader (ifile); + std::vector tarr; + areader.getResourceLanguages (tarr); + for (auto it : tarr) push_no_repeat (vec, it); + } + } + } + hr = pienum->MoveNext (&hasCurrent); + } + return vec.size (); +} +IAppxManifestProperties *BundleReader::getProperties () +{ + CComPtr manifest = this->getAppxManifest (); + if (!manifest) return NULL; + IAppxManifestProperties *properties = NULL; + HRESULT hr = manifest->GetProperties (&properties); + if (!properties) return NULL; + if (FAILED (hr)) { if (properties) properties->Release (); return NULL; } + return properties; +} +std::wstring BundleReader::getPropertiesStringValue (LPCWSTR lpswName) +{ + std::wstring temp (L""); + if (!lpswName) return NULL; + IAppxManifestProperties *properties = this->getProperties (); + if (!properties) return temp; + LPWSTR lpswValue = NULL; + HRESULT hr = properties->GetStringValue (lpswName, &lpswValue); + properties->Release (); + if (lpswValue) { temp += lpswValue; CoTaskMemFree (lpswValue); lpswValue = NULL; } + return temp; +} +std::wstring BundleReader::getPropertiesStringValue (const std::wstring objswName) +{ + return this->getPropertiesStringValue (objswName.c_str ()); +} +HRESULT BundleReader::getPropertiesBoolValue (LPCWSTR lpswName, BOOL &bOutput) +{ + HRESULT hr = E_FAIL; + if (!lpswName || !&bOutput) return hr; + IAppxManifestProperties *properties = this->getProperties (); + if (!properties) return hr; + hr = properties->GetBoolValue (lpswName, &bOutput); + properties->Release (); + return hr; +} +HRESULT BundleReader::getPropertiesBoolValue (const std::wstring objswName, BOOL &bOutput) +{ + return this->getPropertiesBoolValue (objswName.c_str (), bOutput); +} +std::wstring BundleReader::getPropertyName () +{ + return this->getPropertiesStringValue (L"DisplayName"); +} +std::wstring BundleReader::getPropertyDescription () +{ + return this->getPropertiesStringValue (L"Description"); +} +std::wstring BundleReader::getPropertyPublisher () +{ + return this->getPropertiesStringValue (L"PublisherDisplayName"); +} +std::wstring BundleReader::getPropertyLogo () +{ + return this->getPropertiesStringValue (L"Logo"); +} +UINT64 BundleReader::getPrerequisite (LPCWSTR lpswName) +{ + IAppxManifestReader *manifest = this->getAppxManifest (); + if (!manifest) return NULL; + UINT64 u64t = 0; + HRESULT hr = manifest->GetPrerequisite (lpswName, &u64t); + if (manifest) manifest->Release (); + if (FAILED (hr)) return NULL; + return u64t; +} +UINT64 BundleReader::getPrerequisite (const std::wstring objswName) +{ + return this->getPrerequisite (objswName.c_str ()); +} +VERSION BundleReader::getPrerequisiteOSMinVersion () +{ + UINT64 temp = this->getPrerequisite (L"OSMinVersion"); + return VERSION (temp); +} +IAppxManifestApplicationsEnumerator *BundleReader::getApplicationsEnumerator () +{ + IAppxManifestReader *manifest = this->getAppxManifest (); + if (!manifest) return NULL; + IAppxManifestApplicationsEnumerator *temp = NULL; + HRESULT hr = manifest->GetApplications (&temp); + manifest->Release (); + if (!temp) return NULL; + if (FAILED (hr)) { if (temp) temp->Release (); return NULL; } + return temp; +} +bool BundleReader::isPackageApplication () +{ + IAppxManifestApplicationsEnumerator *aenum = this->getApplicationsEnumerator (); + if (!aenum) return false; + BOOL hasCurrent = FALSE; + HRESULT hr = aenum->GetHasCurrent (&hasCurrent); + aenum->Release (); + return SUCCEEDED (hr) && hasCurrent; +} +size_t BundleReader::getApplications (std::vector& output) +{ + if (!&output) return 0; + output.clear (); + CComPtr aenum = this->getApplicationsEnumerator (); + if (!aenum) return 0; + BOOL hasCurrent = FALSE; + HRESULT hr = aenum->GetHasCurrent (&hasCurrent); + while (SUCCEEDED (hr) && hasCurrent) + { + CComPtr app = NULL; + hr = aenum->GetCurrent (&app); + if (app && SUCCEEDED (hr)) + { + appmap map; + LPWSTR lpswTemp = NULL; + hr = app->GetAppUserModelId (&lpswTemp); + if (lpswTemp && SUCCEEDED (hr)) + { + std::wstring objT = lpswTemp; + CoTaskMemFree (lpswTemp); + if (!objT.empty ()) + { + map [StringLabel (L"AppUserModelID")] = objT; + for (auto it : applicationItems) + { + LPWSTR lpswTemp2 = NULL; + hr = app->GetStringValue (it.c_str (), &lpswTemp2); + if (lpswTemp2 && SUCCEEDED (hr)) + { + std::wstring objT2 = lpswTemp2; + CoTaskMemFree (lpswTemp2); + if (!objT2.empty ()) + { + map [StringLabel (it)] = objT2; + } + } + } + push_no_repeat (output, map); + } + } + } + hr = aenum->MoveNext (&hasCurrent); + } + return output.size (); +} +size_t BundleReader::getApplicationUserModelIDs (std::vector &output) +{ + if (!&output) return 0; + output.clear (); + std::vector maps; + this->getApplications (maps); + for (auto it : maps) + { + std::wstring t (L""); + t += it.getAppUserModelID (); + push_no_repeat (output, t); + } + return output.size (); +} +size_t BundleReader::getApplicationIDs (std::vector &output) +{ + if (!&output) return 0; + output.clear (); + std::vector maps; + this->getApplications (maps); + for (auto it : maps) + { + std::wstring t (L""); + t += it [StringLabel (L"Id")]; + push_no_repeat (output, t); + } + return output.size (); +} +size_t BundleReader::getApplicationVisualElementsBackgroundColor (std::vector &output) +{ + if (!&output) return 0; + output.clear (); + std::vector maps; + this->getApplications (maps); + for (auto it : maps) + { + std::wstring t (L""); + t += it [StringLabel (L"BackgroundColor")]; + push_no_repeat (output, t); + } + return output.size (); +} +APPX_CAPABILITIES BundleReader::getCapabilitiesFlag () +{ + CComPtr manifest = this->getAppxManifest (); + if (!manifest) return (APPX_CAPABILITIES)NULL; + APPX_CAPABILITIES temp; + HRESULT hr = manifest->GetCapabilities (&temp); + if (FAILED (hr)) return (APPX_CAPABILITIES)NULL; + return temp; +} +size_t BundleReader::getDeviceCapabilities (std::vector &output) +{ + if (!&output) return 0; + output.clear (); + CComPtr manifest = this->getAppxManifest (); + if (!manifest) return 0; + CComPtr denum = NULL; + HRESULT hr = manifest->GetDeviceCapabilities (&denum); + if (!denum || FAILED (hr)) return 0; + BOOL hasCurrent = FALSE; + hr = denum->GetHasCurrent (&hasCurrent); + while (SUCCEEDED (hr) && hasCurrent) + { + LPWSTR lpswT = NULL; + hr = denum->GetCurrent (&lpswT); + if (lpswT && SUCCEEDED (hr)) + { + std::wstring objswT = lpswT; + CoTaskMemFree (lpswT); + if (!objswT.empty ()) push_no_repeat (output, objswT); + } + hr = denum->MoveNext (&hasCurrent); + } + return output.size (); +} +size_t BundleReader::getCapabilities (std::vector &output) +{ + if (!&output) return 0; + output.clear (); + std::vector dcap; + GetCapabilitiesName (this->getCapabilitiesFlag (), output); + this->getDeviceCapabilities (dcap); + for (auto it : dcap) + { + std::wstring temp (L""); + temp += it; + push_no_repeat (output, temp); + } + return output.size (); +} +IAppxManifestPackageDependenciesEnumerator *BundleReader::getDependenciesEnumerator () +{ + CComPtr manifest = this->getAppxManifest (); + if (!manifest) return NULL; + IAppxManifestPackageDependenciesEnumerator *deps; + HRESULT hr = manifest->GetPackageDependencies (&deps); + if (!deps) return NULL; + if (FAILED (hr)) + { + if (deps) deps->Release (); + return NULL; + } + return deps; +} +size_t BundleReader::getDependencies (std::vector &output) +{ + if (!&output) return 0; + output.clear (); + CComPtr deps = this->getDependenciesEnumerator (); + if (!deps) return 0; + BOOL hasCurrent = FALSE; + HRESULT hr = deps->GetHasCurrent (&hasCurrent); + while (SUCCEEDED (hr) && hasCurrent) + { + CComPtr dep = NULL; + hr = deps->GetCurrent (&dep); + if (SUCCEEDED (hr)) + { + DEPINFO dinfo (dep); + push_no_repeat (output, dinfo); + } + hr = deps->MoveNext (&hasCurrent); + } + return output.size (); +} +IStream *BundleReader::extractFileToStream (LPCWSTR lpswFilePath) +{ + CComPtr bmanifest = this->getManifest (); + if (!bmanifest) return NULL; + CComPtr pienum = NULL; + HRESULT hr = bmanifest->GetPackageInfoItems (&pienum); + if (!pienum || FAILED (hr)) return NULL; + BOOL hasCurrent = FALSE; + hr = pienum->GetHasCurrent (&hasCurrent); + while (SUCCEEDED (hr) && hasCurrent) + { + CComPtr pinfo = NULL; + hr = pienum->GetCurrent (&pinfo); + if (pinfo && SUCCEEDED (hr)) + { + APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE ftype = APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE_RESOURCE; + hr = pinfo->GetPackageType (&ftype); + if (SUCCEEDED (hr) && ftype == APPX_BUNDLE_PAYLOAD_PACKAGE_TYPE_APPLICATION) + { + LPWSTR lpswSubPkgName = NULL; + hr = pinfo->GetFileName (&lpswSubPkgName); + if (lpswSubPkgName && SUCCEEDED (hr)) + { + CComPtr ifile = NULL; + hr = this->m_bundleReader->GetPayloadPackage (lpswSubPkgName, &ifile); + CoTaskMemFree (lpswSubPkgName); + + if (ifile && SUCCEEDED (hr)) + { + AppxReader areader (ifile); + IStream *isfile = areader.extractFileToStream (lpswFilePath); + if (isfile) return isfile; + } + } + else if (lpswSubPkgName) + { + CoTaskMemFree (lpswSubPkgName); + } + } + } + hr = pienum->MoveNext (&hasCurrent); + } + while (SUCCEEDED (hr) && hasCurrent) + { + CComPtr pinfo = NULL; + hr = pienum->GetCurrent (&pinfo); + if (pinfo && SUCCEEDED (hr)) + { + LPWSTR lpswSubPkgName = NULL; + hr = pinfo->GetFileName (&lpswSubPkgName); + if (lpswSubPkgName && SUCCEEDED (hr)) + { + CComPtr ifile = NULL; + hr = this->m_bundleReader->GetPayloadPackage (lpswSubPkgName, &ifile); + CoTaskMemFree (lpswSubPkgName); + if (ifile && SUCCEEDED (hr)) + { + AppxReader areader (ifile); + IStream *isfile = areader.extractFileToStream (lpswFilePath); + if (isfile) return isfile; + } + } + else if (lpswSubPkgName) + { + CoTaskMemFree (lpswSubPkgName); + } + } + hr = pienum->MoveNext (&hasCurrent); + } + return NULL; +} +IStream *BundleReader::extractFileToStream (std::wstring objswFilePath) +{ + return this->extractFileToStream (objswFilePath.c_str ()); +} +IStream *BundleReader::getPriFileStream () +{ + return this->extractFileToStream (L"resources.pri"); +} + +typedef enum _PKGTYPE { PKG_UNKNOWN = 0, PKG_SINGLE = 1, PKG_BUNDLE = 2 } PKGTYPE, pkgtype; + +typedef class PackageReader +{ + private: + AppxReader single; + BundleReader bundle; + public: + PackageReader (LPCWSTR lpwzFile); + PackageReader (std::wstring objwzFile); + PackageReader (); + bool create (LPCWSTR lpwzFile); + bool create (std::wstring objwzFile); + bool destroy (); + bool isAvailable (); + ~PackageReader (); + pkgtype getType (); + // ʧܷسΪ 0 յı + std::wstring getIdentityName (); + // ʧܷسΪ 0 յı + std::wstring getIdentityPublisher (); + // ʧܷضΪ 0 İ汾 + VERSION getIdentityVersion (); + size_t getIdentityProcessorArchitecture (std::vector &arrOut); + size_t getResourceLanguages (std::vector &vec); + LPCWSTR getFilePath (); + IAppxManifestReader *getAppxManifest (); + IAppxBundleManifestReader *getBundleManifest (); + // ˶ȡĶȡİΪ Bundle ָҪֶͷšֶ֮ͷţŶٶ + IAPPXREADER getAppxPackageReader () + { + switch (this->getType ()) + { + case PKG_SINGLE: return const_cast (single.getPackageReader ()); + case PKG_BUNDLE: return bundle.getAppxPackageReader (); + } + return NULL; + } + // ȡֶָͷţŶٶ + IBUNDLEREADER getBundlePackageReader () + { + if (this->getType () == PKG_BUNDLE) return const_cast (bundle.getPackageReader ()); + else return NULL; + } + std::wstring getPropertyName (); + std::wstring getPropertyDescription (); + std::wstring getPropertyPublisher (); + std::wstring getPropertyLogo (); + // ʧܷضΪ 0 İ汾 + VERSION getPrerequisiteOSMinVersion (); + // жϵǰǷΪӦðԴΪĻжǷӰдӦð + bool isPackageApplication (); + size_t getApplications (std::vector &output); + size_t getApplicationUserModelIDs (std::vector &output); + size_t getApplicationIDs (std::vector &output); + size_t getApplicationVisualElementsBackgroundColor (std::vector &output); + size_t getCapabilities (std::vector &output); + size_t getDependencies (std::vector &output); + IStream *getPriFileStream (); + IStream *extractFileToStream (LPCWSTR lpswFilePath); + IStream *extractFileToStream (std::wstring objswFilePath); +} pkgreader; +PackageReader::PackageReader (LPCWSTR lpwzFile) { create (lpwzFile); } +PackageReader::PackageReader (std::wstring objwzFile) { create (objwzFile); } +PackageReader::PackageReader (): single (), bundle () {} +bool PackageReader::create (LPCWSTR lpwzFile) +{ + this->destroy (); + return bundle.create (lpwzFile) || single.create (lpwzFile); +} +bool PackageReader::create (std::wstring objwzFile) { return this->create (objwzFile.c_str ()); } +bool PackageReader::destroy () +{ + if (!isAvailable ()) return false; + bool res = single.destroy (); + res = bundle.destroy () || res; + return res; +} +bool PackageReader::isAvailable () +{ + return single.isFileReaderAvailable () || bundle.isFileReaderAvailable (); +} +PackageReader::~PackageReader () { destroy (); } +pkgtype PackageReader::getType () +{ + if (single.isFileReaderAvailable ()) return PKG_SINGLE; + else if (bundle.isFileReaderAvailable ()) return PKG_BUNDLE; + else return PKG_UNKNOWN; +} +IAppxManifestReader *PackageReader::getAppxManifest () +{ + switch (this->getType ()) + { + case PKG_SINGLE: return single.getManifest (); + case PKG_BUNDLE: return bundle.getAppxManifest (); + } + return NULL; +} +IAppxBundleManifestReader *PackageReader::getBundleManifest () +{ + if (this->getType () == PKG_BUNDLE) return bundle.getManifest (); + return NULL; +} +// ʧܷسΪ 0 յı +std::wstring PackageReader::getIdentityName () +{ + std::wstring t (L""); + if (single.isFileReaderAvailable ()) return single.getIdentityName (); + if (bundle.isFileReaderAvailable ()) return bundle.getIdentityName (); + return t; +} +// ʧܷسΪ 0 յı +std::wstring PackageReader::getIdentityPublisher () +{ + std::wstring t (L""); + if (single.isFileReaderAvailable ()) return single.getIdentityPublisher (); + if (bundle.isFileReaderAvailable ()) return bundle.getIdentityPublisher (); + return t; +} +// ʧܷضΪ 0 İ汾 +VERSION PackageReader::getIdentityVersion () +{ + VERSION v (0); + if (single.isFileReaderAvailable ()) return single.getIdentityVersion (); + if (bundle.isFileReaderAvailable ()) return bundle.getIdentityVersion (); + return v; +} +size_t PackageReader::getIdentityProcessorArchitecture (std::vector &arrOut) +{ + + if (single.isFileReaderAvailable ()) return single.getIdentityProcessorArchitecture (arrOut); + if (bundle.isFileReaderAvailable ()) return bundle.getIdentityProcessorArchitecture (arrOut); + return 0; +} +size_t PackageReader::getResourceLanguages (std::vector &vec) +{ + if (single.isFileReaderAvailable ()) return single.getResourceLanguages (vec); + if (bundle.isFileReaderAvailable ()) return bundle.getResourceLanguages (vec); + return 0; +} +LPCWSTR PackageReader::getFilePath () +{ + switch (this->getType ()) + { + case PKG_SINGLE: return this->single.getFilePath (); + case PKG_BUNDLE: return this->bundle.getFilePath (); + } + return NULL; +} +std::wstring PackageReader::getPropertyName () +{ + if (single.isFileReaderAvailable ()) return single.getPropertyName (); + if (bundle.isFileReaderAvailable ()) return bundle.getPropertyName (); + return std::wstring (L""); +} +std::wstring PackageReader::getPropertyDescription () +{ + if (single.isFileReaderAvailable ()) return single.getPropertyDescription (); + if (bundle.isFileReaderAvailable ()) return bundle.getPropertyDescription (); + return std::wstring (L""); +} +std::wstring PackageReader::getPropertyPublisher () +{ + if (single.isFileReaderAvailable ()) return single.getPropertyPublisher (); + if (bundle.isFileReaderAvailable ()) return bundle.getPropertyPublisher (); + return std::wstring (L""); +} +std::wstring PackageReader::getPropertyLogo () +{ + if (single.isFileReaderAvailable ()) return single.getPropertyLogo (); + if (bundle.isFileReaderAvailable ()) return bundle.getPropertyLogo (); + return std::wstring (L""); +} +// ʧܷضΪ 0 İ汾 +VERSION PackageReader::getPrerequisiteOSMinVersion () +{ + VERSION v (0); + if (single.isFileReaderAvailable ()) return single.getPrerequisiteOSMinVersion (); + if (bundle.isFileReaderAvailable ()) return bundle.getPrerequisiteOSMinVersion (); + return v; +} +// жϵǰǷΪӦðԴΪĻжǷӰдӦð +bool PackageReader::isPackageApplication () +{ + if (single.isFileReaderAvailable ()) return single.isPackageApplication (); + if (bundle.isFileReaderAvailable ()) return bundle.isPackageApplication (); + return false; +} +size_t PackageReader::getApplications (std::vector &output) +{ + if (single.isFileReaderAvailable ()) return single.getApplications (output); + if (bundle.isFileReaderAvailable ()) return bundle.getApplications (output); + return 0; +} +size_t PackageReader::getApplicationUserModelIDs (std::vector &output) +{ + if (single.isFileReaderAvailable ()) return single.getApplicationUserModelIDs (output); + if (bundle.isFileReaderAvailable ()) return bundle.getApplicationUserModelIDs (output); + return 0; +} +size_t PackageReader::getApplicationIDs (std::vector &output) +{ + if (single.isFileReaderAvailable ()) return single.getApplicationIDs (output); + if (bundle.isFileReaderAvailable ()) return bundle.getApplicationIDs (output); + return 0; +} +size_t PackageReader::getApplicationVisualElementsBackgroundColor (std::vector &output) +{ + if (single.isFileReaderAvailable ()) return single.getApplicationVisualElementsBackgroundColor (output); + if (bundle.isFileReaderAvailable ()) return bundle.getApplicationVisualElementsBackgroundColor (output); + return 0; +} +size_t PackageReader::getCapabilities (std::vector &output) +{ + if (single.isFileReaderAvailable ()) return single.getCapabilities (output); + if (bundle.isFileReaderAvailable ()) return bundle.getCapabilities (output); + return 0; +} +size_t PackageReader::getDependencies (std::vector &output) +{ + if (single.isFileReaderAvailable ()) return single.getDependencies (output); + if (bundle.isFileReaderAvailable ()) return bundle.getDependencies (output); + return 0; +} +IStream *PackageReader::getPriFileStream () +{ + if (single.isFileReaderAvailable ()) return single.getPriFileStream (); + if (bundle.isFileReaderAvailable ()) return bundle.getPriFileStream (); + return NULL; +} +IStream *PackageReader::extractFileToStream (LPCWSTR lpswFilePath) +{ + if (single.isFileReaderAvailable ()) return single.extractFileToStream (lpswFilePath); + if (bundle.isFileReaderAvailable ()) return bundle.extractFileToStream (lpswFilePath); + return NULL; +} +IStream *PackageReader::extractFileToStream (std::wstring objswFilePath) +{ + if (single.isFileReaderAvailable ()) return single.extractFileToStream (objswFilePath); + if (bundle.isFileReaderAvailable ()) return bundle.extractFileToStream (objswFilePath); + return NULL; +} diff --git a/AppInstaller/pkginfo.h b/AppInstaller/pkginfo.h new file mode 100644 index 0000000..158b750 --- /dev/null +++ b/AppInstaller/pkginfo.h @@ -0,0 +1,196 @@ +#pragma once +#include "pkgcode.h" +#include "priread.h" +#include + +// ڴϢ +struct PackageInfomation +{ + struct Identity + { + std::wstring name = L""; + std::wstring publisher = L""; + VERSION version; + std::vector architectures; + } identities; + struct Resources + { + std::vector languages; + } resources; + struct Prerequisites + { + VERSION osMinVersion; + } prerequisites; + struct Property + { + std::wstring name = L""; + std::wstring description = L""; + std::wstring publisher = L""; + std::string logoBase64 = ""; + CComPtr logoStream = NULL; + } properties; + std::vector applications; + std::vector capabilities; + std::vector dependencies; + bool isMsResourceLabel (LPCSTR lpstr) + { + if (!lpstr) return false; + const std::string mslabel ("ms-resource:"); + std::string sub = StringTrim (std::string (lpstr)).substr (0, mslabel.length ()); + return LabelEqual (sub, mslabel); + } + bool isMsResourceLabel (LPCWSTR lpstr) + { + if (!lpstr) return false; + const std::wstring mslabel (L"ms-resource:"); + std::wstring sub = StringTrim (std::wstring (lpstr)).substr (0, mslabel.length ()); + return LabelEqual (sub, mslabel); + } + bool isMsResourceLabel (std::string objStr) { return isMsResourceLabel (objStr.c_str ()); } + bool isMsResourceLabel (std::wstring objStr) { return isMsResourceLabel (objStr.c_str ()); } + PackageInfomation (PackageReader &reader) { this->create (reader); } + PackageInfomation () {} + bool create (PackageReader &reader) + { + PriReader pri; + this->identities.name = reader.getIdentityName (); + this->identities.publisher = reader.getIdentityPublisher (); + this->identities.version = reader.getIdentityVersion (); + reader.getIdentityProcessorArchitecture (this->identities.architectures); + reader.getResourceLanguages (this->resources.languages); + std::sort (this->resources.languages.begin (), this->resources.languages.end ()); + if (pri.create (reader.getPriFileStream ())) + { + std::wstring temp = reader.getPropertyName (); + if (isMsResourceLabel (temp)) + { + std::wstring getres = pri.findStringValue (temp); + if (!getres.empty () && getres.length () > 0) temp = std::wstring (L"") + getres; + } + this->properties.name = temp; + temp = reader.getPropertyDescription (); + if (isMsResourceLabel (temp)) + { + std::wstring getres = pri.findStringValue (temp); + if (!getres.empty () && getres.length () > 0) temp = std::wstring (L"") + getres; + } + this->properties.description = temp; + temp = reader.getPropertyPublisher (); + if (isMsResourceLabel (temp)) + { + std::wstring getres = pri.findStringValue (temp); + if (!getres.empty () && getres.length () > 0) temp = std::wstring (L"") + getres; + } + this->properties.publisher = temp; + } + else + { + this->properties.name = reader.getPropertyName (); + this->properties.description = reader.getPropertyDescription (); + this->properties.publisher = reader.getPropertyPublisher (); + } + this->properties.logoBase64 = GetLogoBase64FromReader (reader, &this->properties.logoStream); + this->prerequisites.osMinVersion = reader.getPrerequisiteOSMinVersion (); + reader.getApplications (this->applications); + reader.getCapabilities (capabilities); + reader.getDependencies (dependencies); + return reader.isAvailable (); + } + void destroy () + { + this->identities.name = L""; + this->identities.publisher = L""; + this->identities.version = VERSION (0); + this->identities.architectures.clear (); + this->properties.name = L""; + this->properties.description = L""; + this->properties.publisher = L""; + this->properties.logoBase64 = ""; + if (this->properties.logoStream) { this->properties.logoStream.Release (); this->properties.logoStream = nullptr; } + this->resources.languages.clear (); + this->prerequisites.osMinVersion = VERSION (0); + this->applications.clear (); + this->capabilities.clear (); + this->dependencies.clear (); + } + // ʧܷسΪ 0 յı + std::wstring getIdentityName () { return this->identities.name; } + // ʧܷسΪ 0 յı + std::wstring getIdentityPublisher () { return this->identities.publisher; } + // ʧܷضΪ 0 İ汾 + VERSION getIdentityVersion () { return this->identities.version; } + size_t getIdentityProcessorArchitecture (std::vector &arrOut) + { + for (auto it : this->identities.architectures) + { + arrOut.push_back (it); + } + return arrOut.size (); + } + size_t getResourceLanguages (std::vector &vec) + { + for (auto it : this->resources.languages) + { + vec.push_back (it); + } + return vec.size (); + } + std::wstring getPropertyName () { return this->properties.name; } + std::wstring getPropertyDescription () { return this->properties.description; } + std::wstring getPropertyPublisher () { return this->properties.publisher; } + std::string getPropertyLogoBase64 () { return this->properties.logoBase64; } + // ֶͷ + IStream *getPropertyLogoIStream () { return this->properties.logoStream; } + // ʧܷضΪ 0 İ汾 + VERSION getPrerequisiteOSMinVersion () { return this->prerequisites.osMinVersion; } + // жϵǰǷΪӦðԴΪĻжǷӰдӦð + bool isPackageApplication () { return this->applications.size () > 0; } + size_t getApplications (std::vector &output) + { + for (auto it : this->applications) + { + output.push_back (it); + } + return output.size (); + } + size_t getApplicationUserModelIDs (std::vector &output) + { + for (auto it : this->applications) + { + output.push_back (it.getAppUserModelID ()); + } + return output.size (); + } + size_t getApplicationIDs (std::vector &output) + { + for (size_t cnt = 0; cnt < this->applications.size (); cnt ++) + { + output.push_back (this->applications [cnt] [std::wstring (L"Id")]); + } + return output.size (); + } + size_t getApplicationVisualElementsBackgroundColor (std::vector &output) + { + for (size_t cnt = 0; cnt < this->applications.size (); cnt ++) + { + output.push_back (this->applications [cnt] [std::wstring (L"BackgroundColor")]); + } + return output.size (); + } + size_t getCapabilities (std::vector &output) + { + for (auto it : this->capabilities) + { + output.push_back (it); + } + return output.size (); + } + size_t getDependencies (std::vector &output) + { + for (auto it : this->dependencies) + { + output.push_back (it); + } + return output.size (); + } +}; \ No newline at end of file diff --git a/AppInstaller/priread.h b/AppInstaller/priread.h new file mode 100644 index 0000000..0041052 --- /dev/null +++ b/AppInstaller/priread.h @@ -0,0 +1,377 @@ +#pragma once +// PRI APIֻʹ makepri +#include +#include +#include +#include "localeex.h" +#include +#include "pkgcode.h" +#include "PriReader2.h" + +std::string GetProgramRootDirectoryA () +{ + char path [MAX_PATH]; + if (GetModuleFileNameA (NULL, path, MAX_PATH)) + { + std::string dir (path); + size_t pos = dir.find_last_of ("\\/"); + if (pos != std::string::npos) + { + dir = dir.substr (0, pos); + } + return dir; + } + return ""; +} +std::wstring GetProgramRootDirectoryW () +{ + wchar_t path [MAX_PATH]; + if (GetModuleFileNameW (NULL, path, MAX_PATH)) + { + std::wstring dir (path); + size_t pos = dir.find_last_of (L"\\/"); + if (pos != std::wstring::npos) + { + dir = dir.substr (0, pos); + } + return dir; + } + return L""; +} +std::string EnsureTrailingSlash (const std::string &path) +{ + if (path.empty ()) return path; // ·ֱӷ + + char lastChar = path.back (); + if (lastChar == '\\' || lastChar == '/') + return path; // зֱָӷ + // ϵͳԭ·ʽʵķָ + char separator = (path.find ('/') != std::string::npos) ? '/' : '\\'; + return path + separator; +} +std::wstring EnsureTrailingSlash (const std::wstring &path) +{ + if (path.empty ()) return path; + + wchar_t lastChar = path.back (); + if (lastChar == L'\\' || lastChar == L'/') + return path; + + wchar_t separator = (path.find (L'/') != std::wstring::npos) ? L'/' : L'\\'; + return path + separator; +} +bool IsDirectoryExists (const std::string path) { return IsDirectoryExistsA (path.c_str ()); } +bool IsDirectoryExists (const std::wstring path) { return IsDirectoryExistsW (path.c_str ()); } +bool IsDirectoryExists (LPCSTR path) { return IsDirectoryExistsA (path); } +bool IsDirectoryExists (LPCWSTR path) { return IsDirectoryExistsW (path); } +std::string NormalizePath (const std::string &path) +{ + if (!path.empty () && path.back () == '\\') + return path.substr (0, path.size () - 1); + return path; +} +std::wstring NormalizePath (const std::wstring &path) +{ + if (!path.empty () && path.back () == L'\\') + return path.substr (0, path.size () - 1); + return path; +} +std::vector EnumSubdirectories (const std::string &directory, bool includeParentPath) +{ + std::vector subdirs; + std::string normPath = NormalizePath (directory); + std::string searchPath = normPath + "\\*"; + WIN32_FIND_DATAA findData; + HANDLE hFind = FindFirstFileA (searchPath.c_str (), &findData); + if (hFind == INVALID_HANDLE_VALUE) return subdirs; + do + { + // "." ".." + if (strcmp (findData.cFileName, ".") == 0 || strcmp (findData.cFileName, "..") == 0) + continue; + // жǷΪĿ¼ + if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + if (includeParentPath) + subdirs.push_back (normPath + "\\" + findData.cFileName); + else + subdirs.push_back (findData.cFileName); + } + } while (FindNextFileA (hFind, &findData)); + FindClose (hFind); + return subdirs; +} +std::vector EnumSubdirectories (const std::wstring &directory, bool includeParentPath) +{ + std::vector subdirs; + std::wstring normPath = NormalizePath (directory); + std::wstring searchPath = normPath + L"\\*"; + WIN32_FIND_DATAW findData; + HANDLE hFind = FindFirstFileW (searchPath.c_str (), &findData); + if (hFind == INVALID_HANDLE_VALUE) return subdirs; + do + { + if (wcscmp (findData.cFileName, L".") == 0 || wcscmp (findData.cFileName, L"..") == 0) + continue; + if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + if (includeParentPath) + subdirs.push_back (normPath + L"\\" + findData.cFileName); + else + subdirs.push_back (findData.cFileName); + } + } while (FindNextFileW (hFind, &findData)); + FindClose (hFind); + return subdirs; +} +bool CheckDependency (const std::string &dllName) +{ + HMODULE hModule = LoadLibraryA (dllName.c_str ()); + if (hModule == NULL) + { + return false; + } + FreeLibrary (hModule); + return true; +} +bool CheckDependency (const std::wstring &dllName) +{ + HMODULE hModule = LoadLibraryW (dllName.c_str ()); + if (hModule == NULL) + { + return false; + } + FreeLibrary (hModule); + return true; +} +bool CanRunExe (const std::string &exePath) +{ + STARTUPINFOA si = {sizeof (si)}; + PROCESS_INFORMATION pi; + BOOL success = CreateProcessA ( + exePath.c_str (), // Ӧ· + NULL, // в + NULL, // ȫ + NULL, // ̰߳ȫ + FALSE, // ̳о + CREATE_NO_WINDOW, // + NULL, // + NULL, // ǰĿ¼ + &si, // Ϣ + &pi // Ϣ + ); + if (!success) + { + DWORD error = GetLastError (); + return false; + } + WaitForSingleObject (pi.hProcess, INFINITE); + DWORD exitCode; + GetExitCodeProcess (pi.hProcess, &exitCode); + CloseHandle (pi.hProcess); + CloseHandle (pi.hThread); + return (exitCode == 0); +} +bool CanRunExe (const std::wstring& exePath) +{ + STARTUPINFOW si = {sizeof (si)}; + PROCESS_INFORMATION pi; + BOOL success = CreateProcessW ( + exePath.c_str (), // Ӧ· + NULL, // в + NULL, // ȫ + NULL, // ̰߳ȫ + FALSE, // ̳о + CREATE_NO_WINDOW, // + NULL, // + NULL, // ǰĿ¼ + &si, // Ϣ + &pi // Ϣ + ); + if (!success) + { + DWORD error = GetLastError (); + return false; + } + WaitForSingleObject (pi.hProcess, INFINITE); + DWORD exitCode; + GetExitCodeProcess (pi.hProcess, &exitCode); + CloseHandle (pi.hProcess); + CloseHandle (pi.hThread); + return (exitCode == 0); +} +bool IsProgramExecutable (const std::string &exePath) +{ + if (!IsFileExists (exePath)) + { + return false; + } + if (!CanRunExe (exePath)) + { + return false; + } + return true; +} +bool IsProgramExecutable (const std::wstring &exePath) +{ + if (!IsFileExists (exePath)) + { + return false; + } + if (!CanRunExe (exePath)) + { + return false; + } + return true; +} +std::wstring GetUniqueTempFilePathW () +{ + // ȡʱļ· + wchar_t tempPath [MAX_PATH]; + if (GetTempPath (MAX_PATH, tempPath) == 0) + { + return L""; + } + // һΨһʱļ + wchar_t tempFile [MAX_PATH]; + if (GetTempFileName (tempPath, L"TMP", 0, tempFile) == 0) + { + return L""; + } + return tempFile; +} +std::string GetUniqueTempFilePathA () { + // ȡʱļ· + char tempPath [MAX_PATH]; + if (GetTempPathA (MAX_PATH, tempPath) == 0) + { + return ""; + } + // һΨһʱļ + char tempFile [MAX_PATH]; + if (GetTempFileNameA (tempPath, "TMP", 0, tempFile) == 0) + { + return ""; + } + return tempFile; +} +int InStr (const std::string &text, const std::string &keyword, bool ignoreCase = false) +{ + std::string s1, s2; + if (ignoreCase) + { + s1 = StringToUpper (text); + s2 = StringToUpper (keyword); + } + else + { + s1 = text; + s2 = keyword; + } + const char *found = StrStrIA (s1.c_str (), s2.c_str ()); + if (!found) + { + return -1; + } + return found - text.c_str (); +} +int InStr (const std::wstring &text, const std::wstring &keyword, bool ignoreCase = false) +{ + std::wstring s1, s2; + if (ignoreCase) + { + s1 = StringToUpper (text); + s2 = StringToUpper (keyword); + } + else + { + s1 = text; + s2 = keyword; + } + const WCHAR *found = StrStrIW (s1.c_str (), s2.c_str ()); + if (!found) + { + return -1; + } + return found - text.c_str (); +} + +template StringType ReplaceBackslash (const StringType &input) +{ + StringType result = input; // ַ޸ԭ + using CharType = typename StringType::value_type; // ȡַַͣchar wchar_t + std::replace (result.begin (), result.end (), static_cast ('\\'), static_cast ('/')); + return result; +} + +class PriReader +{ + private: + HPRIREADER priReader; + public: + PriReader (LPCWSTR lpPriFilePath) { this->create (lpPriFilePath); } + PriReader (const std::wstring objPriFilePath) { this->create (objPriFilePath); } + PriReader (IStream *comISPriFile) { this->create (comISPriFile); } + ~PriReader () { this->destroy (); } + PriReader (): priReader (NULL) {} + void destroy () + { + if (!priReader) return; + DestroyPriReader (priReader); + priReader = NULL; + } + bool isAvailable () { return priReader != nullptr; } + bool create (const std::wstring priFile) { destroy (); return priReader = CreatePriReader (priFile.c_str ()); } + bool create (LPCWSTR priFile) { destroy (); if (!priFile) return false; return this->create (std::wstring (priFile)); } + bool create (IStream *priFStream) { destroy (); return priReader = CreatePriReaderFromStream (priFStream); } + // ȡָҪ free ֶͷš + LPSTR findStringValue (LPCSTR lpMsName, LPCSTR defaultLocaleCode = NULL) + { + return PriReaderFindStringValueA (priReader, lpMsName, defaultLocaleCode); + } + // ȡָҪ free ֶͷš + LPWSTR findStringValue (LPCWSTR lpMsName, LPCWSTR defaultLocaleCode = NULL) + { + return PriReaderFindStringValueW (priReader, lpMsName, defaultLocaleCode); + } + std::string findStringValue (const std::string &objMsName, const std::string &defaultLocaleCode = "") + { + std::string t (""); + LPSTR lpStr = findStringValue (objMsName.c_str (), ((!defaultLocaleCode.empty () && defaultLocaleCode.length () > 0) ? defaultLocaleCode.c_str () : NULL)); + if (lpStr) t += lpStr; + if (lpStr) free (lpStr); + return t; + } + std::wstring findStringValue (const std::wstring &objMsName, const std::wstring &defaultLocaleCode = L"") + { + std::wstring t (L""); + LPWSTR lpStr = findStringValue (objMsName.c_str (), ((!defaultLocaleCode.empty () && defaultLocaleCode.length () > 0) ? defaultLocaleCode.c_str () : NULL)); + if (lpStr) t += lpStr; + if (lpStr) free (lpStr); + return t; + } + LPSTR findFilePathValue (LPCSTR lpMsName, int defaultScale = 0, ImageContrast defaultContrast = ImageContrast::none) + { + return PriReaderFindFilePathValueA (priReader, lpMsName, defaultScale, defaultContrast); + } + LPWSTR findFilePathValue (LPCWSTR lpMsName, int defaultScale = 0, ImageContrast defaultContrast = ImageContrast::none) + { + return PriReaderFindFilePathValueW (priReader, lpMsName, defaultScale, defaultContrast); + } + std::string findFilePathValue (const std::string &objMsName, int defaultScale = 0, ImageContrast defaultContrast = ImageContrast::none) + { + std::string t (""); + LPSTR lpStr = findFilePathValue (objMsName.c_str (), defaultScale, defaultContrast); + if (lpStr) t += lpStr; + if (lpStr) free (lpStr); + return t; + } + std::wstring findFilePathValue (const std::wstring &objMsName, int defaultScale = 0, ImageContrast defaultContrast = ImageContrast::none) + { + std::wstring t (L""); + LPWSTR lpStr = findFilePathValue (objMsName.c_str (), defaultScale, defaultContrast); + if (lpStr) t += lpStr; + if (lpStr) free (lpStr); + return t; + } +}; \ No newline at end of file diff --git a/AppInstaller/res/Button/Large/blank.png b/AppInstaller/res/Button/Large/blank.png new file mode 100644 index 0000000000000000000000000000000000000000..4a1239026d4a4972a8e6b73852b214a1e46401ed GIT binary patch literal 1873 zcmb_dO>g8h7|x1iwN$EvIC3G%URc11?PM~EwV~?Hl1su!eA$oR_jw;bw!hfld$76j z>V{z$o4wuc0leR6?%TKE`Q-5rAHwUUV)ui}FkY#f`^GQHYg5Cx^?f=xtPlI|GNCh@ zOC2kFniYUHjC)(tf{Pf?UVQKNMCtW*!r_6FkYNQBbb zdfU7=We^}!H8-c(IIq|=vSx7^d^gRGWzHb=QDkj53C+X)zS+^GGJP8(fw5~6;@eV+ zb}YQNOo}OSaNv+OA}%8VbKBQIURfvVHI=2Mhcca{;lsuE>d)Tz$RCL)jZaUEH}bzVePtitBiLMV{TnexIRHg1ZV z0i{^sisN!TOD=_@#wt^JT>+M?u*FE%x*F*#La(|nBmi;y{Z)=jxn$WYMOE*dKp6`` zE=5;^(?U51s?x`$P&+3;^G;Ju!8)blwJrx*kC#)mzocwZVpH?=M`4h5$f zA1bHFhnBgLk#+P~myj6Px$Et{PG`T=Njip(>fphBv$xanN$C5C+GIwz-)FtNs(CI{ zuNzq)j-95G1w`VQN{rgdCx|MKpjcv#LO1jh<+(DD^KxN)SBvAu0?qjOdXQQ`jDP60 zlt*QPTZkw>MzZZm6nKF^Dh!G1`k2y~FWJ0Trm!UWcs**vN^T!kQ2;<sZfU%(MA&&T_q&OPApPSB%qataFDs z|2E&OZ*3EXiJUdT&fa{k4i)%W9ZM<)ok}=#en00=;J|A4y4!=p$4`H{v1u5$Uod~& r`s>FpKfn3a(~n+$|ElZ!=kph%KR^9C*f{*HIrMrvd);sDfBf0sJP}H+ literal 0 HcmV?d00001 diff --git a/AppInstaller/res/Button/Large/blank_light.png b/AppInstaller/res/Button/Large/blank_light.png new file mode 100644 index 0000000000000000000000000000000000000000..a44303d3bd18e35a17762716872c4b4aa31c3aee GIT binary patch literal 1928 zcmcgt&yU+g7;>VeNmHr++rcGUw(9DBxZ-uJ$5-pqWt zxv_TP{43`*O}o%t?`*;St?F7{g8!d?`t>H<&Jr)3{y_tRQR4LA<`7%WL}^J-)xgJz-qFq_0eTAV_4%^hq*I3xCoyro28p zSKZjqr;u`|X|$?<`gX9Xw^c56$FvZ)EL$hUF@@lbkk{VPsYMC4Tud5>*gkQ6yP?lN z2E@xnvj4V{6vT1{xiWQUcqX~3-2kmVrD?NRE(&!TTzu5Vd0 zXrM$K?Hz}bMvoA`Zu?g47!*t+SjnCU7Tk|io-jx_PFP>!EbSZmqKtl94OI?-L7jcH zzuRta<|>MZ@S<8kdUv($5YKTCHOW+N5cu7+C|Sy7x6?GBIA$CRzd>!!W?_V+Ylq0= zwGg@WT7)8-FeY3=A~{PJ#&;ASRTikm&(?!b95^1zv+J%18?KF57`liMU<+;Tp_*F@ zB_rH%7&}z+K_0`BWW%GZl_~*@mQ5O-WF87@#6@8Qg1oxR5uubeB3kzt^(xy>o#d~_ z11eRbOBQ(IG2bL=^@vF;7cG9ZyX3`B-+kfW;Oy0V%U>*izI5*9iv7py$=9Ple}8arfAq;$AD`;` bp^dYbpZWHeJKy2zIP9)&bZ%ey=(B$T;+J5M literal 0 HcmV?d00001 diff --git a/AppInstaller/res/Button/Large/blank_press.png b/AppInstaller/res/Button/Large/blank_press.png new file mode 100644 index 0000000000000000000000000000000000000000..0376f986f1b7a8396b70f26b919d2412b9c49370 GIT binary patch literal 1928 zcmcgtJ&YSg6y5+ik)TL{3Lzv`8wv3@yEC)v{nMG?*vFkEd>j``Ik*DGGqd(`-koK4 zefAvrZlmgr9ou6;s``(*x-rU^U zT)%Yjxr>^nU21Q%w&DFs^*p%(|3Cfs^Dey372E6Av|G2I{|h=#^c$UqrhWV6Q}@_; z=wHY--YqoknX-D${TaP5(X^GLxVuyCblwWNN=znHPnwe?1GJ{CUY%r&@5xf{$$p&H zjXU3cZ|Je88#ihl+{v195N{mj^7`Rsmmlu&Kp0nF*HJ0yN+d;0ui zfWKTs;dblIxi{$5jX_yvp=FK7V{>eqD(_n)2m%XJi&6v#R2-xwo1nC~varyS1<&KG zj8&>v7Fkb?%DMquXF(*{(rjAH69p-=CM>gviL0QdK*5)|Y?KeD&IPyRP$n`h3&4^k zHXEo?6$5o2)63}-4j{Rm&eF%JT#{tzqA1t)A&hxKPDK~pgG^f6vQVR(%e8%=d8LXb z3!AxQrOLZX4HsLrwVvbr=5mIl?M4Bw z1>6nzg3a4`3`dd;k6W!+39yK5;sufgsOJzL^&%%iLCxogP)fas)&fR@O7>GFg&T1J zdweiINY~{@^VTrdr{W12uMS1s;FTJrFy_PYDfu{)=lS~aK!VW+sAT57P*FK%xoq?y zcMnyebwBb2+kY_iAnFN6*a50R;*p0PiC7N{#68cZK2#5z2aC{8Qa?qtk3xN(7CvBU zUqX$wj7JaVY`UDW{2zm{s=_)`nDt-rP3MjkVc5v&5LEW6xx7@Mv%HpM3VF)m(n-I% z{488p@3dQu?#}w(x5?9=ym9&H=<)aOoZtQCvy}_GtM>0NCSQ#H`1Rh=-O`y5?` literal 0 HcmV?d00001 diff --git a/AppInstaller/res/Button/Large/cancel_window_light.png b/AppInstaller/res/Button/Large/cancel_window_light.png new file mode 100644 index 0000000000000000000000000000000000000000..45e3fe0c5ebeec39a3a72e47b0f8456665ecb0cd GIT binary patch literal 2142 zcmb_dYitx%6dnjK7w`ebA0T!zB`H|uJ-ahI>5A>{+HS&@rrk)5LcDY5&hEhO%rG-$ zw-AYdEoekg`DY>q6OG0|8cBcNnUq*8?pDRN6+KVlx%Cd zl^}+8%=`;X#r^x7j%PfAnBxcUq#uoj5(@&y^DI*cV^)FH884EOP?THN-B0xKt3Q# zg}mjdr5IKAtKxPr%u;08#9tGmT7!UOZ@P<&+b$v_3`awb6G@(rFuD$94N6N$ffIO^ zQ&?W6c~RvRRg}rfC#FGl5j-%(k%SS&I{k+Iz@%SWS8mJ?V(ps@w* z^;IubWO)MZHo*%0?qF8V-&_(NuuD?-CACiC`=h!0uIYFT#!`RP=|Fp zr_arogX@q*c~n4_?_pcMZtLW1-}Z9$ZCuxoCm5AR9-Gy9oHUo3ZVDZL7L!kV%1O1ai>|)6(stw|K$=lmI@8 zQFzxRnv2k!k_mQ=S0$yHQ&f(tn5J#rH2QBg4XZ*#75VE-v1oMQgF71QP&I6~0C2)) z0b~*DSXqj!)2PPnyzSz^7@atAJQa_3xwc{E@kCHSWGWet@X<(w78t$^H=R~fmgfTt zqEsSAVR9JL)Kx>15RbSht!bi613}Vg1uBr1IYH9_40BMBYwHs>>TqS~D>D z8p5Oj1Mr$GiJByWTIx4LmsE~dxoAzb_X5323(Ns4i|`rCQum(B-RZJ|^5$f2D8c_P z88$drD+*(86kmC6!Xb<|vOI)O_Mln6RB)$$Eg=i@iq2!JQH5=~>$!nJI>LTMZ+7&!5hPciUec>^ZRKofB?q{KM7B)1xT$^TPhv v&~$&*zVj!gbDamqjx_n91H1x*)@+F^2b|&_=J-_*1^u5d~ literal 0 HcmV?d00001 diff --git a/AppInstaller/res/Button/Large/cancel_window_normal.png b/AppInstaller/res/Button/Large/cancel_window_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..dd1442cf3863334f3c882b5a92861241ef299f60 GIT binary patch literal 1776 zcmbVNU5Fb+98bk+d$b~@MQjzfTM*lGcV~99Np`t-y(DKY*qkv9^t4i)%*-asWp~!y z%_SFKJW)Yk1W{;x9w_?Y`EX#7at{^yQWV5DMQ8KnwY`2|V6*e_ zo8SNU|Cs;2U7F7C9N9Y(i^X;prgCNeJ`_FM?&JR}%ikU6ukGH{^Fb`OD~z5km#xRz zvDnr>?8;0yQ#@i~=E#V!DwW%g$I-Fa*m&DRc$S7jmDX%GE&g`#OHr^%T0Eu~LD9?7 zx;@qL>Cw(~1$Sn#LB#Q=gt4~C2^<z-*_*F0aYQ(Xt{6T}U{a7AGQu!c4Iw zWSLKegbXAMfF?kgkO{%bDvm!Xs6d4ZNGUKWLCu6IQ%ef{pUCa`#4^jdr~B6UEG^c< z&@&aK)oRHtO=f;gfreoyKvh&#;s`02cSF>c+~B}~Ax8u3+g@lhSBMxr)gmzrt8!kgC!^ zvY!7@72nx|1!33KY^Bu$;wjETXis#luVHid;%Noq*hPgUz<9Z>RE&0r{8+;=u=QBcK zGMj)#A|a_V?8+?`&4L?*$i=jfON%@>vTYMHuEzm1uqwqN#S)+Cl7S2=A!Hees!AZ= zADquI+>A;fI^VkwgkjF{pFB-dK@ugC645Lm@w1kc(ljLL6cMWHfRL0mV0+fL`ISVC zjjWL>!Wn^{Frb#yC7J?If-r7K)r6%>D%22-_JE;AW#6qNbIJ~Qj_3Oq=_q}rKWf-Q zw|Gp1qf3z%aa0YIi2Y@IlX%>f<^K6ropRFKR7uZzz^t%^d^%C%vAbgxDz_3Jpt;*i zzq?fSG~F!yhN}HP()(e-b>!A4@3D#)Iip0qsFxJw#(Z`6HuS9loHxU0IPAlGGVJ8k z<9dgVm^%-CP==bi1B z4_gm^_}=5rJ>@r!WZoRvbEvXZT3lV+w|?)HcP{OCWMO67)l>N^%D1n+_!?zbwe?5m zUO2z6nIA{95B$_Td1B$TczpWr-D|sl?xcTxY5zaF_MZ83|62#Y>6||Q`-LwSM?e0d yo%w!g?V_RFWIJ~VrVQID5T2%9{{3+1+`3 z^ZS0^H@|OYO>@)S3I2QhKA&$wDw$}Z|A)M{ZY=%o-`l^K{%V|-xwCyczNkMzJGI$Z zI_C53TzlI&cq{FXw~~t-pYJZ$duzVW+*kDZ#(u1~wY%-Fs}k#oxaEcO>R0}^>IZm`Fz!d<2Ej%VU!bc zMQf+6+ag>Gam+3ok;Y||=2R~lOO4wEx~AP`nz_nWHCHGzq7V?7X$y4&n+4~=Q42@{ zx+KcdU6TMW13uE`?V70a@^n6;^8AQt+QfRM`*PEeDuypLrJ}*mh1WI4NX?jb9@2pI zJj@c#GO{dFO`{q&bEZulQ+C18DMTw9gs;p0#sLPXpw|=A^u!$(f z1$v66WE3HTK?Fe&gu@;h6f*#aVMya85+otHg7&Db(~^X_(Wo9POc4o`GIB`9085Gj zh$IOBYP73JP>_RI5HSjQvM(t~P3jKa;iXzG)PYndKNz()+ z1H!VxBLr~-BCQho<;|6eei zcd(8qjJs5PrMXduFx|+~5IxzwX7y5`o$9qj44NmKUOI>WN<2p|zv-z&tgU_S@83lI zdmf&+>gcI)wXN-&p2%tN=-mw~R=@RkUCopadQb24*U2v~I95};|I;}qvwH$FI$1nC z#s8~C4Y^kK(yI4-Qqv2KIjP{Pu~RFUW=TxBCvAw^Ikc{_Opp180-olKKCx+%oRi zy5t?h3-=v(cgni@!G8wLTPFMaV_Scy8w1WBKlAcaE9So;N<*6cc8!1W_?K1>Mo$ba zs$Fn9n0@$AyRiHG*++JtNp4=-HL(6op?BLmlQ#Ui{`IdW^&a1Kb4ou#V-V*J*D2kQZ)SfY4f~QXo@4ELx@1jpNHYIkk44ofy`glX(f`u%tWsIx;Y9 z?C1WI$O`0h7I;J!GcX91fH32|H2DgkV5O&vV@QPi+Z!8s8x#Z_E?!<(!g>9|!Wif2 z1zNf5mNb0e?)`5X5b)=Tlas`(yH(v-vN1BHABSy|B@ryAB^p*o1!QkoY K=d#Wzp$PynHdE*T literal 0 HcmV?d00001 diff --git a/AppInstaller/res/Button/Large/max_normal.png b/AppInstaller/res/Button/Large/max_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..4fcdd76be069e4ab13aa93b2bf55d76f2073ec6c GIT binary patch literal 1466 zcmbVM%Zn687;ho#V^Ih}f(T;SqL^rRS9Q;`ur=$<#2K(R!#d!K2d$~DnQ3;qtL?6J zX7?1ti+J;zkbgi32)PCHAUSx;K|wD$sP<;QQ!C7Y%ibP zv$%gz)3iOUW_<<5@3X#hJN*B8@bD50yW-}>RMWmuS>N_g@8DR|7WM_5RkiA!qg;k2 z^JQ0<<1hxarky-Jju~GQ3Ux(4h+O@}pZ9eX_^y7T=wUCei9yiZOvL%kV1VrU!=qm+(aeZos&o^4w?nn2W=t1o2&(W=)*HJJ!hGO@uib`T*Y)AxC~ z%L^xvjcsD#ibcu>aVV)!r;KJz2YHF#qbv0vXVPHh>I0=>YFVSv$Q(JQO!^k7R;w1a zE!#E#VWb<8Vq+sp56>CuBIQXCt3XC5V`N>qu3Q~-of;9wIc=2A90e}3#w@moi8G@n zK%eKhcs&_Tg!|kQLlKHdrGO8ns@UHC(8&@my`*q3Jvk;iy_doOgPe}kt z$cA6clci=BJG2?3@TwcL)HyG%&St{^O~QpTo~41S^X&bFug|uFFZRHcb~F$``jNPp z!cy5&BbJDzK6vYsac6<@R+g|+JFNekI62#r+;ccojBJ`0D_G>^PDD`S5-4Uz9`1Ms zg|OMGFLhQQJb!$5mxgyXmR??d)&IG3=&Qo7|Iu4_{{`;9L*WUp6G055g literal 0 HcmV?d00001 diff --git a/AppInstaller/res/Button/Large/max_press.png b/AppInstaller/res/Button/Large/max_press.png new file mode 100644 index 0000000000000000000000000000000000000000..53b911a0fde7e6ddeb1d8d6e7e76330c9243cb96 GIT binary patch literal 227 zcmeAS@N?(olHy`uVBq!ia0vp^S|H591|*LjJ{b+97>k44ofy`glX(f`u%tWsIx;Y9 z?C1WI$O`0h7I;J!GcX91fH32|H2DgkV1=iPV@QPi+Z!8s8x#Z_E?(YSB9?o{Q@Xs+ zFn8UOh7a7m|4jn|{ycGVl313y|1tBinE3Mnvlf~-XSQA9St{veJmuO~xxMFf%S)eq zJrQf|?*Ce@_N_(qxoH+vvledof9IE&?e=@~g-~>)X=p!UOrI_u`F$e`$Qulvu6{1- HoD!My?F8(B6tua2dig#+D)?gz=EExu6pWupZBBQ z`Lw@%>D2lw>zbyW>ULT?>iuT%3oR+KaM$p80+F>Ri*-{)z{? za<}&`rXn#36A?G(Nv6=6cJBNsJ{Z5VgIziH?(YZzBHd$5-^`8e(z=KS*E z_JAJl(U2ME-`3B~u_8#gB>Fs=qy?Tgj0G=N^K#iT^aVujHH@v&puXGd>rIh!-7_Je z5IQDD!9E~ZR1!iNm83A zWP4w^Q3d2!bTK%{xV6IzG0iD&?<<)br8gOF=A1~84}_SkQq^Bc)@@|k`s-KXl!;mK z#*qWOMI>(+Dr+u)9)Q81OxY&3H_yTVL%4+Y1dE3U4?{x?5k}}fs45ypBzYp3Q9KlR zLX^XCLPp%m(vhLpVZ==_5xFv~)Hz4jyUk`l7sGg>Hj14~7xiwt>7mf`fNi3M++GiN z(?XJz@@}hPsNk4!%&-%2Xa^ny0kR#yeAfqI6f(e(g91+2W)K9c^DRNAWeJq$m-m4Q zsyP0WM{FN@%(Ve>10VQ~8-d96hX8qD#CSw(?u0A0_wra>NisRgTB>4-(RKV_$T^UIBs8a&b7`ul@_Mjs7cd)EExPyE?8-+giWll7NYL*A7aZeIW4*R{2^JI|lK j_VvBPel>pn^5s9y+-|>ck44ofy`glX(f`u%tWsIx;Y9 z?C1WI$O`0h7I;J!GcX91fH32|H2DgkV78}=V@QPi+Z!8s8w_|D9NQP35L)Bdmc$#O z6zuqzRjAf+$^K({@kP%!&HpaVeWU2#yoDytnQfPNmP&dVPf61_8!!tZFpYC=ox_*c sCvtsq{qvG-Y|q{ohRXpJpX&O-AZ^KI>9cC)a-g*gp00i_>zopr0LgDiCjbBd literal 0 HcmV?d00001 diff --git a/AppInstaller/res/Button/Large/min_normal.png b/AppInstaller/res/Button/Large/min_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..efe7ffc84d9420735d4e33d6b6f8755a71e4682f GIT binary patch literal 1880 zcmb_d&5zqe6n8;k3piA80U-_`3Wwe*ap1r|zy)ywapT!ZOctddsydSG@yu`D`@Q#mGxPCa z@5a`}OBW?c+Uo6g_u>0`^;|d)@1O79dk;R(WxKZuNqYXp>NzKU_W4VabpD5Ucvv3x z-|?wPRKi5a)p?QuT9U3_pJ#*~@lp=?C{6?A&+oohf8qd2``B}PbO*M&jY2l>qEa9))cvhlt+Qmt{lpT{ej#OIhSn}BZ{#p z>$|+WueOpn#Wlgi&U;Gl2A;`Kmo3cAd;*xn-PI3^2m~A_WW=>B9Vv2?M!zE_A_vF7&RiewbvlDwMDYYBiv1hga&M<&>z-{RL)B}# z{l4Ezi;|?2_qu@s$x-8&`C-f8jv2Yg2|=7KY(>a3b&9OW)?FAf4Feq274y4-PAdsi z>lgch2?{p;qemjsCAJM&W44Q^Wwnrt?G}nchMCohA|5tu-pym!l4P=OwPMAcq4ps11v!2=b=Tsq?GO)zl-f{0 z3!^Y>g^0I8t{bisxvsMceIs?tH}OifPeOf}7CI*Bh{GAHDNi2Ep_VDoTAHRIH zB}o^aY5#Tm((Fs~<$Hhs`svr-4&G{?X}7n(c{X@qdSy_z`ybvv_s{P?9=xJ{a;Lic NdOLgFJKOJn^e=_UNM8T| literal 0 HcmV?d00001 diff --git a/AppInstaller/res/Button/Large/min_press.png b/AppInstaller/res/Button/Large/min_press.png new file mode 100644 index 0000000000000000000000000000000000000000..c367ae764c553c15ec1bb0da8de0d57abd52e06e GIT binary patch literal 213 zcmeAS@N?(olHy`uVBq!ia0vp^S|H591|*LjJ{b+97>k44ofy`glX(f`u%tWsIx;Y9 z?C1WI$O`0h7I;J!GcX91fH32|H2DgkV3wzgV@QPi+Z!8s8w_|D9NYJv(7BMJo^eC9 z+wn20P_5&V{m1m;i=JFVdQ&MBb@00Qt!2LJ#7 literal 0 HcmV?d00001 diff --git a/AppInstaller/res/Button/Large/min_trans_normal.png b/AppInstaller/res/Button/Large/min_trans_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..8e9a54f25c76222d1edcc05f47a7a6685f88e0e8 GIT binary patch literal 1880 zcmb_dO^@3|79BT7vcTWz5DOO=eewRyHJ$pU#y-B%I9Caq$n4Eh)4V7{@`7o z$wa4IhC*K?8K4#A+Koj<*?}n4P>ka=(0>2!drggbpzSpVc#yTlB<>yO;@0ubh#em= zk83xstJfAj5G10c>LQt@g}(^2n%9SZHEd{V4Ji)-tyLLR_Xk6@EpwqdIz|j*TQyBb z=bSY|M&42_Y?%gj4YP?%+c#a`ZmO%MfxVnZ{%+@;l{NSav`JZJzG2MgbA4{>G9MeJ z=XnOU49h}*K*dp7(gjM3t80diC|Dk6Wh_&*Vx*y*m4OCYmrf+vhBhr$fr5}33z`|G zjw`2XAZHs~Hp{2Aan1}e6^Tg8000eh1*w{EzOOk9%6lM1i z+*k$VOms0i%7n2i3OUP}=pKU1tCcsI-_8XsWj>N}x=z(_Em^fp-BMrMi&HM=#p@>) zhz>19ph4CM!Vbdj2(m`7Z#r*c*T;AX9Y`KWNB@O-fbfZX3JOKTX-OXo=FE>|o=|W& zPUu(|SvuC#O&I;QoXQ*wgF5@Fj4H@+*bSDwqtsZgDl;w7V#!z3Z1Ze$@631+#DyR+T`tez_mGWWe#S zJW8o&HKQg9h3z0hi9jJX8>qn|)3vzg+74N>y_d(ZCF%4eYo&?6cw zk>%C;`9uKeBdTO+y^v8kr@3g2A$E_gLgPH~1wDMUbe9O%X;Ke`j6v`tf>9VYLL?fY zFfF$kxh|w~sp(AV#JBOfYM(~>iknSnIu>xo8rsu4^JH~-o-+?^!T--0qdHiZ6=pnK zeD&OkLl_cS55dV^bvKs^{A{izkwTnuxOC7Ty)Il>*ZZB;X#d`CKYz8QD3_jT{dwog z{7d`g`+xoN+1K9=-)^01cecNIHh5w7%CK$^K6-HB?_Yo1dsYARZguzdyE~n`+aG-V E4;E8N8UO$Q literal 0 HcmV?d00001 diff --git a/AppInstaller/res/Button/Large/restore_light.png b/AppInstaller/res/Button/Large/restore_light.png new file mode 100644 index 0000000000000000000000000000000000000000..3552d68544aacfb0b4d96a0901a962a627b9afc3 GIT binary patch literal 243 zcmeAS@N?(olHy`uVBq!ia0vp^S|H591|*LjJ{b+97>k44ofy`glX(f`u%tWsIx;Y9 z?C1WI$O`0h7I;J!GcX91fH32|H2DgkV27uRV@QPi+iM4T9SkHK9vX>wM>H>7b5LlR z(xhFJp4Dqk`X2k`!G{d**?BSFzA)$RtDCpb#5uF=633_&hXsNp0|*40IENr>mdKI;Vst0KT7FqW}N^ literal 0 HcmV?d00001 diff --git a/AppInstaller/res/Button/Large/restore_normal.png b/AppInstaller/res/Button/Large/restore_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..8aad4d54d6a9317c62a59ee8065ccf58d5a50a24 GIT binary patch literal 1473 zcmbVM%a0UA7;mEx*o2EGg9j?j!PoYydY+YS*V&ns8A9)FmWizKVog=eOlPON+OFE2 znLX-7&i(_$i-Cju0URJ995@n;M>&}o6T%HHB>MF{I*XzNDqUT#U;VyEecyL=XY0b5 zm9r~`VVvo-Te~oRocB{F;eYS${jXp+owmPJhVib>`&+;D&rJ;D#CuV9Pw$172$Qi* zx$Fsh5~qMRjJ5SiO4+{9s3!(d5|~eJ-8NCg1M^Bbbi=eMhEe+{6PJ&+y6kA5)w#L; zDO#HlAc%#gXcCVSMJ9nc<0UZ9w;dDBAbLMA8@WKV7w({@%mk{~uEku}N1j))IcL=# zE3G2zV$X4Fj#srjpLjLmSJ9%GATQ&6vfKK6Aq`f6In+8Ojx!#Q?XhpmY~XnHdfjoc zgRun&OHC6^Csv})FBw`wu`Eh;BomY~(w;offeE_Kjfm5NHc<;lfyphf+&5l>b3p9KRp{oEwIPjF;*X$At)`HxI##g+pG7 zR^4eToL!;hLB_=9A*gviwgLeM${Z6yFlgWNGf&;aCVFPtGn-#BKsaV+dX6l9^=_E?igo#co zFu^%?6me3mQ_N`zaH3qZO1y-vUb!kPjNNjj=hl2y$IJUI$qw=mSl;Kad4D^LAPMQ{ zjd}9a%wvbNBL%NIU8K%s@y%j3iqI@v2xWO11SZShUvP7=9lfy!=CtFX0Mh@7i#bfm zz8=#|GzQ?USH_(K$~$?&&h2piY2xhcSaL7nP%-jpQLJE5lsl0?jmw~zJzW3p9Vmp` zomQi}clYtH-iqO#di&1vzaAbw`DLTA`T2*YJN|n_ess&sJ|*tNHzx^Be+sncL literal 0 HcmV?d00001 diff --git a/AppInstaller/res/Button/Large/restore_press.png b/AppInstaller/res/Button/Large/restore_press.png new file mode 100644 index 0000000000000000000000000000000000000000..a848ece01fbe7b4ee7e49c96da76295712a2ed40 GIT binary patch literal 242 zcmeAS@N?(olHy`uVBq!ia0vp^S|H591|*LjJ{b+97>k44ofy`glX(f`u%tWsIx;Y9 z?C1WI$O`0h7I;J!GcX91fH32|H2DgkV7sS_V@QPi+iQk=4h9kq4~z8A9eU)a^X^fS zOOSTvzv)Vq_ZKxkyg1G5uEG14?6+$E+Bj#nUE*0P>18}6P2;Wk!V`x1(aUXiUGMjn zo4UG8&Q|`})(ex&C3#DYFCGg1Z!-6~t>5445?-stq;7gF&yxSMB5VHzjq4g`17m@_V8jW8KN;B^Roy6ej>gTe~DWM4fuFYD9 literal 0 HcmV?d00001 diff --git a/AppInstaller/res/Button/Large/restore_trans_normal.png b/AppInstaller/res/Button/Large/restore_trans_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..bc01f58469b3efcedc3bac02acebdeeb81c578c3 GIT binary patch literal 1692 zcmbVNO>f*p7&byhB~mXO>7kZ;;4A)i{4t6to86FIR3}loqCs33&y07itUbn_WOsAq zM9=(z3Lzmlzz^U6QpJHI0&%1#B!q-|K!OVryx#Siv`s&RCEMefXP)FCJt6^B zuDvdA&JYk}OkjDIP4WuOLS?~=U|dh@ioAe`qfqJ82Ia$OU+(gf$*yLo#4v2xG+m8S z;>E;Smo39Gb;H+9Pc?01`pEX==2F03NfUI?d$X|yU!gJt?_cCn?Vrh zhNWAU3JA5D=K{~vyt=w#=&_2FX(3Xc%QYj8`LPHU(7JRYD_YvTY61lz(`UHQP0gsC zS^z0&am8^tSs158XA_pOTvUKHTWm4rf>&ey2FEb1drx_kG zy~sz3+=dZ#`Gl8X7}VKk=Lg;He#w(`0t?l_&Xzpb?z(2+x~ip_3%OB*26-iLPS~Iq zDi9nkO(`Jq$S+bdHzl6Z2KwN^!e(F=$byRoY>Z^Kau1696h z`zj?4VJ7x*9BkBOzo;bCPb!GB`j{$NTCaE_rnqFC5yb9^Rj5Boe1%UQFa7CKxzzNq^arZ;|447bLdG~BG3c?n zQahv9y=a*f{lR=K*3R^;6&#vjJ#70he6*dMe98QXvY`LBZ$!#a?vbq6ka=HS^~C-uLFs%){NCyVtJ1 zb=5G8YrSq~58iLr_m#`=`~W}x8eVVY-GkCFu2=Pa>DTz3sbO6HF&XSv`~8oZ(5cO( zj+8x3b3hx$osDVE#i6RqNDY&$W&QEp50;t8mUX|;$NjvmMoIUyQ1?!E2IBNkgwoph z(7ZEc5Fk|*H>c@1E7`PV&EhinuA3dpoI$F?mbF0+SucsW(OOUfoCHZ^bEPco?|<$G%bREJlp zWx=d@2>S>J14?Q5CDC+pBAplc{0j0R_*U>eCQej!*27V9GAP;ip+ zp>pzUXqhV+SzC{F0f~W~yWZYww|5I2Cu8U+_wH_)z3sM7Lf=Q!CNsMIKI>&=#WSIL zot6dS*hwN;)DSX|lpr?>D59PxP~;JUNKuLR#Zhg6di;DnNG%}7zw{c) zqcX+~M3f&P+4Lj|yg(oohQxJ!OlicI(LN~>Sdx6a9<^pAA)-ec5yx>8NzaRsa^VpP z>7y9?B%&(j#8b8HXHH_>q=Y#>SuCV`>hs0dI5B7DVO-RUqGgHN4N6*z=HwhbUMllq z{A8pc=zq9mp1ss@HQ|NY9D;Tiy3lzM`H~-BKs^TK8zDhlg&4F zZ@yXI+9nJWIctKQz5ZMsD)6&9mQ)5h6>#YM`QZD%;J~`o>ue6X4}brOTr!L+ubIDW wJp1a=>o?5wx2-49xBIu>{PHQh{%(Hy?#~BLpM3M|pg!e#+dG}dTc3UL4=1ffVgLXD literal 0 HcmV?d00001 diff --git a/AppInstaller/res/Button/Normal/blank_light.png b/AppInstaller/res/Button/Normal/blank_light.png new file mode 100644 index 0000000000000000000000000000000000000000..3328fa799f9e6e48d84b6e77bf702bf9b77b29ff GIT binary patch literal 1904 zcmcgtO^@3|81@4Fps*J%AcTtLN(cmFd&Z8xXsFU;X(I5lO@q3KOUEklC)sqj+J2~qCUNW;Kl8lL`_3~nw|BO$ zZC-fwf}$v!y>6!u_lxy){w(~zYaV_Fw~exY?W%J4`)hZh@!YT#wiM<2uU`0%o`LrB zdH0i2QC_O*YvYgj^_ilay^{=ftKIO!fXP&+Tt-5lr8%G#34`+XHs6$9%3`c~8AO3xFUM6;)^HI4gr$Q(N!`@LYEr zn!12gdrhrX2UK^%9kneBp*p&Wm}y!n#*WT8b0cQIqY{%~!}JX7B5VcN3oKV%eKd$y z@Hpsq-d{z7R#O{QRUR0|bUM|imM)8-fqmaMOkxm%0D;PRR?!*C%1cKK9Z|9($*V+W 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 literal 0 HcmV?d00001 diff --git a/AppInstaller/res/Button/Normal/cancel_light.png b/AppInstaller/res/Button/Normal/cancel_light.png new file mode 100644 index 0000000000000000000000000000000000000000..bc89c71b210e8dd417c865d15989be95a7b0258e GIT binary patch literal 1921 zcmb_dOK2oT7@nwvb!9!MtPnw)4uYaJUDdDYZg$*cXOf*+wzF|Eun|01Q&m0FW~Qs{ z?qnu8dQuQp&z>YAg5W{Cc~DSLP{DW*_adtxco0R=n-c$?mx;_iSRAHbRbPGo_y6@( z)ywN^=TDtnI9VtZPStDG20S0muM>B`{r!gfCp_+sYtN*G!hKnO&3zX{H5_fd>RVkx^yP>qej)4i-HkFjKvB9lVW^6fC1IR}GE#Cz+LGH@Sp}`5Bzp0bHcH2Z zf|6+i8f&D8^Q4AA&Zf9{JLwLCbEb)|=!qyx0ZXRXxFa)}cI0)ar`^W_KyiJ48e^uG zUT+#A%~p0Gjd4L{qSNMXEVPD5<#xiv$_~g}%(IETN+M_`lctp2$yBXRBr7^8>dIr6 z!-&g%`uLFnqDnJSR$d2Xm+zBZ#^tLoJ)zNH~@aOf7?%!G!Hn62g+C-J`6zDh`ac zp>x-upx&kw>82@=>re+dxE0t!cT1MgbK4J{?#r zv0Y?2ri)W7}rdiSr>=A3?+S`#n=4KrlwFT_4ntJ=m+?p?EB{O3Q z{(s46`NleOnD$@u4f~F4!Z4A;CfM2Y*Xf}GAJbz=L{O&$4xRZgvL!gM+V$#kv-T+) zT>JUr;wSj|Ki)prU)?zP>B`nOfBpUYkGsor?iqEKqxQo0Z{06{S$fESr|Dv?X%{%i$vc9rbefQjRFa85kBVz&p literal 0 HcmV?d00001 diff --git a/AppInstaller/res/Button/Normal/cancel_press.png b/AppInstaller/res/Button/Normal/cancel_press.png new file mode 100644 index 0000000000000000000000000000000000000000..6cc0e3cde2b2f0e11999f014d3b9037f3579f037 GIT binary patch literal 1921 zcmb_dOKjXk7e8m`q`MJLL$c5yabP?i@0zSV#&)us z961%K5|1keAi)8tAd%jBsRSoZAS8N#17W-`6107&Vzsu%<8QwI`~Uf7 z=B?G0^Rvh2jthb?+iZAi{CTRn?z@NIzgTl`@W=gGXRGYEq{xGo&cJUQh1n zGRxbF>bkB1HAT|^M}T4{EpZ>D#r&ATqXo(1tc+PIR*X1cTV+k+T8Bv_*@QMNMup-f zQ~EelR2f!D4S*q;;Igf}I|v>Ug?4E|)3V@Lb%M=0tYk%p-GqAb`A7g>T;HF>n5rd7 zCLxM)ahsv`p^LC;gZ%QK5GVm7JyDm(~zd}|Fh6R5DuX}3*%_#C{(pus)|gAOzjAinQYwj@r-E)~MRAvZDAvxO6Pt^5OLZ*^ zXtFwx>-(sg79~yzZF)6{7e|ic5Lr=V1c6R~<7gHzso_>F3T#3#wxAUd(-@EU7}=^U zP>mn1hmaA@@vl6KTEw6h2CjuQ;1VMO*f0pdwn6mBg$}lzG24Ya=1UTH53^RP!b+8{ zg|3dddJAKq83qNegB{?&AhM|D+9uU1+Yg+C8gaqrcxSYb*6ACgRyP(0=0TWLi=rlx z$_+G>M&0qWdfZ9m(fD46a?)G4WEj0*QQ5;eU1;;#-PVQ5&BPaY`_|G8$2P6NHh`g8 zE-)QFl{gG2poYoIPVspiXTF@4%#j~-#ao;~S*B7A_2tMK=Ic;)hA7xtFkp7ZU!nGgG( V_wv>EzON3+=HiO?>ABb5{0APfU!?#5 literal 0 HcmV?d00001 diff --git a/AppInstaller/res/Button/Normal/max_back.png b/AppInstaller/res/Button/Normal/max_back.png new file mode 100644 index 0000000000000000000000000000000000000000..92b54c2ac3ee06e98093e15bfda81c5e8dae2ec4 GIT binary patch literal 1449 zcmbVMJ&)8z7&ZkFLAoYIgi^rBG@!&EqS498@$@^VqzEa9zYvzU{Me!t({*E0lu2Oz`P=U%k~}bPuZC`zw!}zwjxurUXs6GP#;nQBjVoxq zAV3fcO;Hg~lAIKQIpZa;E{`1(%^-Rln46_Qv={E8mdXV3ZP#M1TSFN8Hs`D{VD+z% z=X%(2*BsoiaE;(KQfr{aXM((pN2J&OW+4rBfjQDTC5|(lPVH&UR@u)ePqt!R^c;V5vKQ_$4Gwp$uC19Dd3 z(t~U=6V90HUpSjjk1mpHCO8|M4M_6m=LwP z<@%Pp*7rQ()kxj@(p@92JBNmf%job#=qkbZ9VjFXr<#5c%o&MP7E>@-#&js0G#Q$x zawBP}iON7QXjeOa-fgvZGZo1RT;#p&YpA=`@^RDmEzia?b;FQ!lU&n;iEcYE!8x{+ z986jrP&aB=yk3tiQG?%rao>tu9}hecQCt_x_ie=v$`n|>=l}EljZ8uj(#c2jl%-kb z4(Z4oqI$R}om=AmVl|OymM(;{vJ3)~mGKwcTpY`f_Q0HWIubzoA9*o{(QR+`J1^Kj zZ{BP?ySo3~&4=68`Cp5df6y5JvR~Y}zOwq{^GA2ri{9U($IW|x{q!8R>BCe0_~+M> Rjm@%|cDHugPp|EN`xZh0$p!!b literal 0 HcmV?d00001 diff --git a/AppInstaller/res/Button/Normal/max_light.png b/AppInstaller/res/Button/Normal/max_light.png new file mode 100644 index 0000000000000000000000000000000000000000..10bb4a65b240266b85d2e0150d3574f564b78824 GIT binary patch literal 1869 zcmcgtyKf^!99}>mI4K}eAVd*Xn}*l!&WzXl7|xt>cAQvu4#8*XLdSR>_7d;Tvb%|$ zhzdl3#1-^(p`fAyQBXiZOMz&hfQCN+ilak<-}*&@at~dB<$cZk=KFoWZ@!uNaBp{e z?b36X48vIK?6i9DT(7RjABOuEz35MPJdy3ZSs2FCWpzFDt9pKF7>|7$_xH>F?sdv_ z;xM5H(wQb1L>tECE7Oee16i5_IgHbW_50V~SY|95*3Ehsb+e`%#XBdtym7MI=O+g| z64sU1%*#^>0EsM_IZeiCL8lFChD+hSYIZGi7E&HGtj#K+x!>J0n>v@K?;x8aR5LO5 z9U*uy;NB}HK?J)fba7zg8pR>41?J*sLB3ol+H18J+2E^Tjmk2kt~;4boJq~m`Ow8t z6uF4FgxC;a7sqMIrgmCvED>6=;CY;tu};kjkqz`=*|31?yoe-Q!KTGRD3HvZvdqN} zs*0Kg3ciZV4)gIWx!|rG%S5JS0kL=$n~ij-i;=zq^s4(@0uZ;`UFEotOOmWo6y??t zl(7)x!sw!ZoJqGQ3w@Y#xpf3IH>zqf+RP;@b>7!{yqv1NC1sOfhnO$ij8mZ}#fxVK z$QCPQ!-84!Y~=Qysje6u|6jFrdpPCA(*^;8f{6 zVNh_Ku%UFbbZD6?8EI3Gbq5YM0-7tVM(&_S=5S^07Q?}2MnnIa6Dzp z8r%k4__jhm9uTP*_GD%InUm;FT)-S3FBZ}b`Oe~P9Gf%qP{yl8(Xe>s1_|}do8t@g zxUbBM@sp7R(7U)~o~F>MoUmMO4nezny3oB7`GOtYow{ODNe{&LF&D7UfcTNBE4v=l z)Bpv@k36+3{XF#xT>Bu@7qajXONSEnSl4>+V(!nEbC&;OF>bZ7&K>6d*L<_SGn+6> zIm*);PNM%k_=#(A&2^`{A_x)Y|Fa zzdic?Pb2ba`_}rq?H^zI;3IYWjnnO0>rb{HG5&b<=kLGz@{^CN1Fy5S+xqh26o=(&5@76^@yG63S)$AC?d?kVI5sQg(q%j|-Zi)OIJWP0 z??jb|A`V4^t=)I|?z4lW)*emyfkA1EZ zlL-|{bDCs;*0d{Ery1k>veZL4jMJv^_xC>*Rdz{Pb$2$Xlyw4lL zxcZTPW$J^0M3zjSCgZg5r%hvK*N1*JY#I6tQtmg6&B~#^7wqaSl}p_-G2$58Iw77Z z1h0kM`B0~r5)0QYQbWY{N!_<=`rv zhJ~p`DFOs4j?$7%QCe&)Ewp99^EfMGmFks67OI1?X#m%G5J|Q&n-+^iLCUNt%PeBz zDySJy@D(mQ$j3A1f?IMd6PcC;V95%bjZ~?Mk$Q~j)$|z$klY|x`8bzLlB`@5<<=pD zu}H|d=wfh`Nvkglb&zwpbqF*!s%SF5l}lEte4x~LS*qP7Wt|d}>X&ZBsZf*R@~H)~ z%}UucplS}n9>Vnjr9QQNhkk(TKE`usphO%UorRLxfDqrMP~$UD5RG6Zdn#CPKT>(Z zAmBJ*LuqB{(9lp>D`AJkV=#682CLW*hYEv`~Ua3I}V=)|` zlaFWeyjVXONig~ZmCU^tDk>)|mzzV#-BVR)J&t_A4xdb2FxQpLCP)Z}qB@7;K}L&7C@g zp^&p7IN7W2>QaH9)wLv3$WsoN&ZWP8cmNlc-D__Sx@-K~;H%!o&-k;4-~4jYd3){T z-#=fy``d_q-MPR1dFR*nzxXnG`02^^{q?sxuV`=Fy@zh^|Ndrm;q|t5+7GVXy7M2f CN=n86 literal 0 HcmV?d00001 diff --git a/AppInstaller/res/Button/Normal/min_back.png b/AppInstaller/res/Button/Normal/min_back.png new file mode 100644 index 0000000000000000000000000000000000000000..709a12a3acc4e6ccb442da221a071e99ac94385c GIT binary patch literal 1443 zcmbVMJ#W)M7UQj1t}IiC}&vCr7oChY=3 zVqju|0f_}hBqSsj!~jgpFd+v10h9?CIp@PFsDQw-eP7Q#@ArFqdFlMr!6OG1MVYEq zD=Tt5ntlhy<^L3X@=y*FQT0lqD2GJ)jeYc{dy2CEuwP#jYtBVXd7u-QH<{iGB8gU% zxih_p&~+w2lePTNR(D>!RDti>>gucmov6&(esw!$m$#SdbbFmzu6pJ)nCoFl5HLYN zFX)5`?%8Ue7t49NZK$9R5$m=(p9%zP&N3+Tn1O;0H40%4AXLy@mlm5ee-fC`L0HOjWbCO+5M&|}vA8MC7&>H6bW-1nn6bhV zz7bQlxGB|~Nv(-+Ic7xgxXyWJ6sqNs%D_ar368D$q076;@m&{Kg$QP=GHQ7Z7BpC@ zn~XPdW^Wr;(~gR2mHB%0&8K%y zCzP|3`_RtIXV-6ui93_4kFS039^H7|fQKi?FWvt<{r>r@#+Rw@V_z@a{dVtxb|r12 MwZ)~%lZD33A0u literal 0 HcmV?d00001 diff --git a/AppInstaller/res/Button/Normal/min_light.png b/AppInstaller/res/Button/Normal/min_light.png new file mode 100644 index 0000000000000000000000000000000000000000..17675eac163ce6fd7b3767c4ada47987a3532298 GIT binary patch literal 1864 zcmcgtzmMZY7&RaeoU{!cCj`dZfMD#IaqQTmGpD^|?-FrYR=G&GR4|?yCuU=hv7JqJ zOQ@*$BM=BtP*ET#06_=MNl-#VLq`KOd`_}q7w!Gf6-2Q;9>00t`@VTI^Zx$cjjcg*V)=m@9JQ(bo9bGEZw=ohJyCxyNEv0D3 zqVx13y0XaNoom{ zVuLGY<#ZWb3P(*aIX(X@teZf+&M3)(dgwu?V zl~d$n%iNTab@Wu15E#_CXZ!n|&VH$rbP6A;;f-r%f4Ae4(DxCw$x`lM!1{Sr^IWKY zH?p8OcA84orf%r+I6*3KV-$*3i~_Hfpu{Dd%YcwXthVC4 z*W>3C1*G?I$trrKlX}iewKIm=-PeWA-NaY?=-$#LOqCQuAxcz;0w0RcTdt41AjT>t z)N3oS!b;P5=@+>6VWh9Q#f0Z$1$(SxJ$y0`=F9&*8K>D;R}ORjYrf^TGn+6>yE~)amcXz5a&!B8{Pv%p-1+eO2bZI!vH0lk r-yVPO=il#4p7l3Yy$!(wv$QX=yI#QnZ28l$g-Ln>6Q+U?aYLo#39M< z%x(!46%7R~LP%5yBq}JN;2$^%I-sGUqk$T}%&*%;dp~pqqe0ZDQlh;fNr&}?aT` zY)oxR5g<@?n%8`e@@jh>p{puUrbV6V+-M^5kv^^?6Syvm$cjzayjlqblG$@!*u=t3 zQ463H8(eW*P8Z3gu+>y$Dz7WRk`1<)=vr43eV@>q&leJaxN*G6aVeK9+oY)Ky%Q*7 zCCH`dYIs^Gd!Q!0yMXqYKpK^DqibysP%L`RR?Rz1|=3XUcHm%QqQW_&J9pq zUaQE2S#uHg5DtcvhVaMqbsU5kFQKuPX>xiIO8g-qVcP-p1t^$C@|r&sEJc{;GUHHi zn(?u+i+pSv8yUlnp6U`313Tw@f4|c?D0Pxf;X^gJb;IcIbv(j64^fLO=*Dr_&#Ri} zLiM|m3F263DnmyQ$7dc!k~##b#N{Ypn4kd5wo=L?G+34k=2(R&d|su0U9N4 zf>=8ch)_!Xgti%{tg-#VNntOoV2)2$3+c9cZ`GQn#=<-y7tNxGOwqVONpsbmUZTe% zWnPV+O%w!ufJ>IyE1lFcUaH+OX!lST+V>-0@skHrXURyq(qX6#!XqEM3h@z^Ncg@( z1K2$r!Pcc;q<)EOABXx%7BS)ZSiv4^n~z`2qxo{l@_#JGZZ_7X!|eZ>Z}IKiCJYm~ z=z^WSX>JY`c-b6FDhHiPICS!lpL+ogEUVw$9rm`wSMewP?H}>Ge|>THvzs4Xjhe>% s^M8JS>Vu#ExI1~NefHDj+ZVT5*RlHa>z!YJY0kR--hTJX8}GdTFS0j9wEzGB literal 0 HcmV?d00001 diff --git a/AppInstaller/res/Button/Normal/restore_back.png b/AppInstaller/res/Button/Normal/restore_back.png new file mode 100644 index 0000000000000000000000000000000000000000..c10da8b633ee35835ed5aae4c125ec26083d41dc GIT binary patch literal 1450 zcmbVMOK2NM7~Vh{l3-tQ?4cRfl)kc0tyj|2>zCwMg03rMK^zi@N3$bouy$v=JGNw> zN>2$r6>`cYP)Lr31bS-0xAt7$PeV=8v**`4arUG!K7-=}KI?ohr&TnT-p7b*>K;<%4UywI#RwuP_y%P6E+p z`Y?Onw@ZR*@W zwrN|2Su(7mW)-ki!i6H5d@9IGf(~w0Z%(Aa&Qp6*#@H|hgMmIM=pyMFR=Hd@Oxv(+ z4G>zoA4xLQqI7P`P-Q7icr3YyP{v5wVpn=9=sGqcjC0y3oj3|yW(-MeSh|@RH39}S z$HluzeQai%8|#9+)w4$eHN0 zwI4I1$x^YKP`0)QYR+ZW#JG|$B1O^?qCX8)W2!Q;E!{?+-r`Xp2I*%f9Qlt+MNCwr-8o^?h8AQb{7p>Qzq#&*+>7 zxLvZ^CD$!z^Nw56<_iwf%7ns}ST=P?$?TZL>HDgnyIK6F?}PvO{_BK81(N=`d9u39 z5(n3K3L)K})XgUQX0qyYG|ClBXjTKBO0(dzK%E@(b9-P+JLoYWeOFS9F{$Xt0ZG_O z7hLt;j59!UBP-Rh5ysp0jqXmA^%M@hB3tHd3O0G8V-a+>1lrjBq`3?&aIs!pY1Mu^ z{^QvdW%+XD_kWLMbTRy8`Q_^8->)w}3_n)4x3~X({KEO+*H2zN<<}REzkN-f96q`? dJ2P{4X6Ya2`JZ==Uj3AH)B4&*^>B6jyEnx+#w7p% literal 0 HcmV?d00001 diff --git a/AppInstaller/res/Button/Normal/restore_light.png b/AppInstaller/res/Button/Normal/restore_light.png new file mode 100644 index 0000000000000000000000000000000000000000..3eada01899ba2d87e13f066e003fd4704daad2ea GIT binary patch literal 1873 zcmcgty^q{P6gMCth?EA2h9X!#MIwT+XT1IpAKaNHj@>5IpY}cj%5pDX?UFK7RAw@4fe%nfJFg zH!fay>4Kst7d!3NHvBKu?{iPX_v>x{A^e`t+qX(Zd7-M`r+!Udo+!$*-=^K&YB#zO zFgesIm$A?%!yM3xa`oCIr)*DDYAkwb7HYqL_r0d3Jk)O55svbv=%?+&LhKxFcG=+` z^SO5I4fX0I00To&QFSsLWMwc3wW-|z+V!xZsZ&U`7iz1uLv=UWQk$|6s-t7XFm9-X zI6CLdjhXeDYGRWZ*fWTWNFyL#&~VlHqk+GIC&6}WeeMl%J))r|jM^&f+*I5w5d}%f-=ZS)p855ct zM8|bdQy^zcTs|rWQ|Fu+VjzYht4hF~&2uFdMI8FTi+)izH8zgVQ+Tb_oe=E5PuP7M=@8#>kg1a?-6#q= zSy|DHiB2ojATxTJ@*p-z%sj_Nf_oHM++ry9go7AMh;7o?#=gB+-;!)p*S}sr+YDSX zu<;K)?g>wjBt~u=6J#b9MZRwf==yH#nK9v}zp(aJk-~nYgOgTkR=j5Ak=S#b2C^;3 zLw3Uw$fpdtl$gw-9!{`ZYkn%Dpq-Xb;Dh-t+7a*0TZ2@cDkq?<-Vve3YAFb=&4<&o z^6@yH=j+FP0Y=Z0$jo&qlWI&0vD$;gJyL(hdCW_?|KGex;#w{?;p9oUgB${N^q?4s zJF(?6+hVSjEaE=R`wYoG3H5nSSf6G+0jH~>J$W#XC(0Si|1lV&K2m4$GXAZ+>D-Cq z7YaEYf-}8tF0T{lEH5OHL7ob@ZjL`09l=!AId3 z-Ld}s@KfvOk3PP&{=sK&-`lu*>Gt|F%EQa|AH4Y6A6M#2 Oud}w<`s(^S@BIxL<53O( literal 0 HcmV?d00001 diff --git a/AppInstaller/res/Button/Normal/restore_press.png b/AppInstaller/res/Button/Normal/restore_press.png new file mode 100644 index 0000000000000000000000000000000000000000..d64f607f7c756bba621e15dcb36ac33eb5341a70 GIT binary patch literal 1873 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 A5C8xG literal 0 HcmV?d00001 diff --git a/AppInstaller/res/Icons/FileIcon.ico b/AppInstaller/res/Icons/FileIcon.ico new file mode 100644 index 0000000000000000000000000000000000000000..074eb28387990bcbf77fb67e57152c00ddf2779f GIT binary patch literal 53039 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 Ct3#Rq literal 0 HcmV?d00001 diff --git a/AppInstaller/res/Icons/Main.ico b/AppInstaller/res/Icons/Main.ico new file mode 100644 index 0000000000000000000000000000000000000000..1ba811ea36a93040c277755652afea8a7f1e7c30 GIT binary patch literal 35596 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 literal 0 HcmV?d00001 diff --git a/AppInstaller/res/Pictures/Trans_old.png b/AppInstaller/res/Pictures/Trans_old.png new file mode 100644 index 0000000000000000000000000000000000000000..6e3f92d4c5e50a61217dd2d346c0076136a64208 GIT binary patch literal 1988 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 B)^z{? literal 0 HcmV?d00001 diff --git a/AppInstaller/res/manifest.xml b/AppInstaller/res/manifest.xml new file mode 100644 index 0000000..44d54ca --- /dev/null +++ b/AppInstaller/res/manifest.xml @@ -0,0 +1,25 @@ + + + + + + + True/PM + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/AppInstaller/res2.h b/AppInstaller/res2.h new file mode 100644 index 0000000..08b8476 --- /dev/null +++ b/AppInstaller/res2.h @@ -0,0 +1,156 @@ +#pragma once +#include "resource.h" +#include "pkgcode.h" +bool IsEqualLabel (std::wstring str1, std::wstring str2) +{ + std::wstring s1 = StringToUpper (StringTrim (str1)), + s2 = StringToUpper (StringTrim (str2)); + return s1 == s2; +} +typedef class _LABEL +{ + private: + std::wstring objwsStr; + public: + template explicit _LABEL (const T& str) + { + std::wstringstream wss; + wss << str; + objwsStr = wss.str (); + } + _LABEL (const _LABEL &label) + { + objwsStr = std::wstring (label.objwsStr); + } + _LABEL (): objwsStr (L"") {} + friend bool operator == (const _LABEL &l1, const _LABEL &l2) + { + return IsEqualLabel (l1.objwsStr, l2.objwsStr); + } + friend bool operator == (LPCWSTR &l1, const _LABEL &l2) + { + return IsEqualLabel (_LABEL (l1).objwsStr, l2.objwsStr); + } + friend bool operator == (const _LABEL &l2, LPCWSTR &l1) + { + return IsEqualLabel (_LABEL (l1).objwsStr, l2.objwsStr); + } + friend bool operator == (std::wstring &l1, const _LABEL &l2) + { + return IsEqualLabel (_LABEL (l1).objwsStr, l2.objwsStr); + } + friend bool operator == (const _LABEL &l2, std::wstring &l1) + { + return IsEqualLabel (_LABEL (l1).objwsStr, l2.objwsStr); + } + _LABEL operator = (const _LABEL &other) + { + if (this != &other) this->objwsStr = std::wstring (other.objwsStr); + return *this; + } + _LABEL operator = (LPCWSTR &lpWStr) + { + this->objwsStr = std::wstring (lpWStr); + return *this; + } + _LABEL operator = (const std::wstring &obj) + { + this->objwsStr = std::wstring (obj); + return *this; + } + std::wstring getStr () const { return objwsStr; } + LPCWSTR getStrC () { return objwsStr.c_str (); } + bool operator < (const _LABEL &other) const + { + std::wstring s1 = StringToUpper (StringTrim (this->objwsStr)), + s2 = StringToUpper (StringTrim (other.objwsStr)); + return s1 < s2; + } +} LABEL; +typedef std::map MAP_LABEL_UINT; +bool isinitcapmap = false; +MAP_LABEL_UINT capmap; +void InitCapabilitiesMap () +{ + if (isinitcapmap) return; + isinitcapmap = true; + capmap [LABEL (L"internetClient")] = internetClient; + capmap [LABEL (L"internetClientServer")] = internetClientServer; + capmap [LABEL (L"privateNetworkClientServer")] = privateNetworkClientServer; + capmap [LABEL (L"documentsLibrary")] = documentsLibrary; + capmap [LABEL (L"picturesLibrary")] = picturesLibrary; + capmap [LABEL (L"videosLibrary")] = videosLibrary; + capmap [LABEL (L"musicLibrary")] = musicLibrary; + capmap [LABEL (L"enterpriseAuthentication")] = enterpriseAuthentication; + capmap [LABEL (L"sharedUserCertificates")] = sharedUserCertificates; + capmap [LABEL (L"removableStorage")] = removableStorage; + capmap [LABEL (L"appointments")] = appointments; + capmap [LABEL (L"contacts")] = contacts; + capmap [LABEL (L"phoneCall")] = phoneCall; + capmap [LABEL (L"backgroundMediaPlayback")] = backgroundMediaPlayback; + capmap [LABEL (L"pointOfService")] = pointOfService; + capmap [LABEL (L"allJoyn")] = allJoyn; + capmap [LABEL (L"phoneCallHistoryPublic")] = phoneCallHistoryPublic; + capmap [LABEL (L"microphone")] = microphone; + capmap [LABEL (L"offlineMapsManagement")] = offlineMapsManagement; + capmap [LABEL (L"objects5D")] = objects5D; + capmap [LABEL (L"objects3D")] = objects3D; + capmap [LABEL (L"graphicsCaptureWithoutBorder")] = graphicsCaptureWithoutBorder; + capmap [LABEL (L"bluetooth")] = bluetooth; + capmap [LABEL (L"lowLevelDevices")] = lowLevelDevices; + capmap [LABEL (L"location")] = location; + capmap [LABEL (L"humaninterfacedevice")] = humaninterfacedevice; + capmap [LABEL (L"recordedCallsFolder")] = recordedCallsFolder; + capmap [LABEL (L"proximity")] = proximity; + capmap [LABEL (L"webcam")] = webcam; + capmap [LABEL (L"graphicsCaptureProgrammatic")] = graphicsCaptureProgrammatic; + capmap [LABEL (L"userNotificationListener")] = userNotificationListener; + capmap [LABEL (L"userDataTasks")] = userDataTasks; + capmap [LABEL (L"userAccountInformation")] = userAccountInformation; + capmap [LABEL (L"usb")] = usb; + capmap [LABEL (L"systemManagement")] = systemManagement; + capmap [LABEL (L"spatialPerception")] = spatialPerception; + capmap [LABEL (L"smsSend")] = smsSend; + capmap [LABEL (L"blockedChatMessages")] = blockedChatMessages; + capmap [LABEL (L"chat")] = chat; + capmap [LABEL (L"codeGeneration")] = codeGeneration; + capmap [LABEL (L"voipCall")] = voipCall; + capmap [LABEL (L"enterpriseDataPolicy")] = enterpriseDataPolicy; + capmap [LABEL (L"inputInjectionBrokered")] = inputInjectionBrokered; + capmap [LABEL (L"remoteSystem")] = remoteSystem; + capmap [LABEL (L"inProcessMediaExtension")] = inProcessMediaExtension; + capmap [LABEL (L"webPlatformMediaExtension")] = webPlatformMediaExtension; + capmap [LABEL (L"previewStore")] = previewStore; + capmap [LABEL (L"confirmAppClose")] = confirmAppClose; + capmap [LABEL (L"runFullTrust")] = runFullTrust; + capmap [LABEL (L"previewUiComposition")] = previewUiComposition; + capmap [LABEL (L"slapiQueryLicenseValue")] = slapiQueryLicenseValue; + capmap [LABEL (L"localSystemServices")] = localSystemServices; + capmap [LABEL (L"packageManagement")] = packageManagement; + capmap [LABEL (L"packageQuery")] = packageQuery; + capmap [LABEL (L"packagePolicySystem")] = packagePolicySystem; + capmap [LABEL (L"storeAppInstall")] = storeAppInstall; + capmap [LABEL (L"appLicensing")] = appLicensing; + capmap [LABEL (L"broadFileSystemAccess")] = broadFileSystemAccess; + capmap [LABEL (L"allowElevation")] = allowElevation; + capmap [LABEL (L"unvirtualizedResources")] = unvirtualizedResources; + capmap [LABEL (L"extendedExecution")] = extendedExecution; + capmap [LABEL (L"appointmentsSystem")] = appointmentsSystem; + capmap [LABEL (L"contactsSystem")] = contactsSystem; + capmap [LABEL (L"phoneCallSystem")] = phoneCallSystem; + capmap [LABEL (L"userDataAccounts")] = userDataAccounts; + capmap [LABEL (L"userDataTasksSystem")] = userDataTasksSystem; +} +// ʧܷ NULL +UINT CapabilitiesNameToID (LPCWSTR lpStr) +{ + if (!lpStr) return NULL; + InitCapabilitiesMap (); + auto it = capmap.find (LABEL (lpStr)); + if (it != capmap.end ()) return it->second; + else return NULL; +} +UINT CapabilitiesNameToID (std::wstring objStr) +{ + return CapabilitiesNameToID (objStr.c_str ()); +} \ No newline at end of file diff --git a/AppInstaller/resource.h b/AppInstaller/resource.h new file mode 100644 index 0000000..d1272f2 --- /dev/null +++ b/AppInstaller/resource.h @@ -0,0 +1,162 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ ɵİļ +// AppInstaller.rc ʹ +// +#pragma once +#define IDR_MANIFEST1 1 +#define IDR_VERSION_ZH_CN 1 +#define IDR_VERSION_EN_US 2 +#define MANIFEST 24 +#define BLANK_NORMAL 99 +#define BLANK_LIGHT 100 +#define BLANK_PRESS 101 +#define MIN_NORMAL 102 +#define MIN_LIGHT 103 +#define MIN_PRESS 104 +#define MAX_NORMAL 105 +#define MAX_LIGHT 106 +#define MAX_PRESS 107 +#define RESTORE_NORMAL 108 +#define RESTORE_LIGHT 109 +#define RESTORE_PRESS 110 +#define CANCEL_NORMAL 111 +#define CANCEL_LIGHT 112 +#define CANCEL_PRESS 113 +#define BLANK_LARGR_NORMAL 114 +#define BLANK_LARGR_LIGHT 115 +#define BLANK_LARGR_PRESS 116 +#define MIN_LARGR_NORMAL 117 +#define MIN_LARGE_LIGHT 118 +#define MIN_LARGR_PRESS 119 +#define MAX_LARGE_NORMAL 120 +#define MAX_LARGE_LIGHT 121 +#define MAX_LARGE_PRESS 122 +#define RESTORE_LARGE_NORMAL 123 +#define RESTORE_LARGE_LIGHT 124 +#define RESTORE_LARGE_PRESS 125 +#define CANCEL_LARGE_NORMAL 126 +#define CANCEL_LARGE_LIGHT 127 +#define CANCEL_LARGE_PRESS 128 +#define IDI_MAINICON 129 +#define ICON_TASKBAR 130 +#define ICON_FILE 131 +#define ICON_WHITE 132 +#define ICON_METRO 133 +#define ICON_COLOR 136 +#define WIN_TITLE 300 +#define PAGE_LOADING 301 +#define PAGE_1_TITLE 302 +#define PAGE_INFO_PUBLISHER 303 +#define PAGE_INFO_VERSION 304 +#define PAGE_FUNCTIONS 305 +#define PAGE_CHECK_RUNWHENREADY 306 +#define PAGE_2_LOADCERT 307 +#define PAGE_2_INSTALL 308 +#define PAGE_3_TITLE 309 +#define PAGE_4_TITLE 310 +#define PAGE_5_TITLE 311 +#define DIALOG_SELLET_APPX 312 +#define DIALOG_SELLET_UNI 313 +#define BUTTON_1_SER1 314 +#define BUTTON_3_SER1 315 +#define BUTTON_4_SER1 316 +#define BUTTON_5_SER1 317 +#define DIALOG_WINTITLE 318 +#define PAGE_1_APPHASINSTALLED 319 +#define PAGE_2_TITLE 320 +#define PAGE_1_APP 321 +#define PAGE_2_LOADING 322 +#define PAGE_2_INSTALLING 323 +#define CLHELP_1 330 +#define CLHELP_2 331 +#define CLHELP_3 332 +#define CLHELP_4 333 +#define CLHELP_5 334 +#define CLHELP_6 335 +#define CLHELP_7 336 +#define INITWIDTH 400 +#define INITHEIGHT 401 +#define LIMITWIDTH 402 +#define LIMITHEIGHT 403 +#define textSupportCPU 450 +#define textSupportSystem 451 +#define textSupportLanguage 452 +#define textDependency 453 +#define textDependencyItem 454 +#define internetClient 500 +#define internetClientServer 501 +#define privateNetworkClientServer 502 +#define documentsLibrary 503 +#define picturesLibrary 504 +#define videosLibrary 505 +#define musicLibrary 506 +#define enterpriseAuthentication 507 +#define sharedUserCertificates 508 +#define removableStorage 509 +#define appointments 510 +#define contacts 511 +#define phoneCall 512 +#define backgroundMediaPlayback 513 +#define pointOfService 514 +#define allJoyn 515 +#define phoneCallHistoryPublic 516 +#define microphone 517 +#define offlineMapsManagement 518 +#define objects5D 519 +#define objects3D 519 +#define graphicsCaptureWithoutBorder 520 +#define bluetooth 521 +#define lowLevelDevices 522 +#define location 523 +#define humaninterfacedevice 524 +#define recordedCallsFolder 525 +#define proximity 526 +#define webcam 527 +#define graphicsCaptureProgrammatic 528 +#define userNotificationListener 529 +#define userDataTasks 530 +#define userAccountInformation 531 +#define usb 532 +#define systemManagement 533 +#define spatialPerception 534 +#define smsSend 535 +#define blockedChatMessages 536 +#define chat 537 +#define codeGeneration 538 +#define voipCall 539 +#define enterpriseDataPolicy 540 +#define inputInjectionBrokered 541 +#define remoteSystem 542 +#define inProcessMediaExtension 544 +#define webPlatformMediaExtension 545 +#define previewStore 546 +#define confirmAppClose 547 +#define runFullTrust 548 +#define previewUiComposition 549 +#define slapiQueryLicenseValue 550 +#define localSystemServices 551 +#define packageManagement 552 +#define packageQuery 553 +#define packagePolicySystem 554 +#define storeAppInstall 555 +#define appLicensing 556 +#define broadFileSystemAccess 557 +#define allowElevation 558 +#define unvirtualizedResources 559 +#define extendedExecution 560 +#define appointmentsSystem 561 +#define contactsSystem 562 +#define phoneCallSystem 563 +#define userDataAccounts 564 +#define userDataTasksSystem 565 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/AppLauncher/AppLauncher.cpp b/AppLauncher/AppLauncher.cpp new file mode 100644 index 0000000..fb48515 --- /dev/null +++ b/AppLauncher/AppLauncher.cpp @@ -0,0 +1,31 @@ +// AppLauncher.cpp : DLL Ӧóĵ +// + +#include "stdafx.h" +#include "AppLauncher.h" + +HRESULT LaunchApp (LPCWSTR lpswStr, PDWORD pdwProcessId) +{ + if (!lpswStr) return E_INVALIDARG; + if (FAILED (CoInitializeEx (NULL, COINIT_APARTMENTTHREADED))) return E_INVALIDARG; + std::wstring strAppUserModelId (L""); + if (lpswStr) strAppUserModelId += lpswStr; + CComPtr spAppActivationManager; + HRESULT hrResult = E_INVALIDARG; + if (!strAppUserModelId.empty ()) + { + // Instantiate IApplicationActivationManager + hrResult = CoCreateInstance (CLSID_ApplicationActivationManager, NULL, CLSCTX_LOCAL_SERVER, IID_IApplicationActivationManager, (LPVOID*)&spAppActivationManager); + if (SUCCEEDED (hrResult)) + { + // This call ensures that the app is launched as the foreground window + hrResult = CoAllowSetForegroundWindow (spAppActivationManager, NULL); + // Launch the app + if (SUCCEEDED (hrResult)) + { + hrResult = spAppActivationManager->ActivateApplication (strAppUserModelId.c_str (), NULL, AO_NONE, pdwProcessId); + } + } + } + return hrResult; +} \ No newline at end of file diff --git a/AppLauncher/AppLauncher.h b/AppLauncher/AppLauncher.h new file mode 100644 index 0000000..70c06e4 --- /dev/null +++ b/AppLauncher/AppLauncher.h @@ -0,0 +1,13 @@ +// ifdef Ǵʹ DLL 򵥵 +// ı׼ DLL еļ϶ APPLAUNCHER_EXPORTS +// űġʹô DLL +// κĿϲӦ˷šԴļаļκĿὫ +// APPLAUNCHER_API ΪǴ DLL ģ DLL ô˺궨 +// ΪDZġ +#ifdef APPLAUNCHER_EXPORTS +#define APPLAUNCHER_API __declspec(dllexport) +#else +#define APPLAUNCHER_API __declspec(dllimport) +#endif + +EXTERN_C APPLAUNCHER_API HRESULT LaunchApp (LPCWSTR strAppUserModelId, PDWORD pdwProcessId); diff --git a/AppLauncher/AppLauncher.vcxproj b/AppLauncher/AppLauncher.vcxproj new file mode 100644 index 0000000..c8dafb4 --- /dev/null +++ b/AppLauncher/AppLauncher.vcxproj @@ -0,0 +1,250 @@ + + + + + Debug + ARM + + + Debug + Win32 + + + Release + ARM + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {285130BC-CBF1-4C7A-A28D-6F5EE6C68384} + Win32Proj + AppLauncher + 8.1 + + + + DynamicLibrary + true + v140 + Unicode + + + DynamicLibrary + true + v140 + Unicode + + + DynamicLibrary + false + v140 + true + Unicode + + + DynamicLibrary + false + v140 + true + Unicode + + + DynamicLibrary + true + v140 + Unicode + + + DynamicLibrary + false + v140 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + true + + + true + + + false + + + false + + + false + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;APPLAUNCHER_EXPORTS;%(PreprocessorDefinitions) + true + + + Windows + true + + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;APPLAUNCHER_EXPORTS;%(PreprocessorDefinitions) + true + + + Windows + true + + + + + Use + Level3 + Disabled + _DEBUG;_WINDOWS;_USRDLL;APPLAUNCHER_EXPORTS;%(PreprocessorDefinitions) + true + + + Windows + true + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;APPLAUNCHER_EXPORTS;%(PreprocessorDefinitions) + true + MultiThreaded + + + Windows + true + true + true + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;APPLAUNCHER_EXPORTS;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + + + + + Level3 + Use + MaxSpeed + true + true + NDEBUG;_WINDOWS;_USRDLL;APPLAUNCHER_EXPORTS;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + + + + + + + + + + + + + + false + false + + + + + false + + + false + false + + + + + false + + + + + Create + Create + Create + Create + Create + Create + + + + + + \ No newline at end of file diff --git a/AppLauncher/AppLauncher.vcxproj.filters b/AppLauncher/AppLauncher.vcxproj.filters new file mode 100644 index 0000000..156a8e8 --- /dev/null +++ b/AppLauncher/AppLauncher.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/AppLauncher/ReadMe.txt b/AppLauncher/ReadMe.txt new file mode 100644 index 0000000..ffec762 --- /dev/null +++ b/AppLauncher/ReadMe.txt @@ -0,0 +1,30 @@ +======================================================================== + 动态链接库:AppLauncher 项目概述 +======================================================================== + +应用程序向导已为您创建了此 AppLauncher DLL。 + +本文件概要介绍组成 AppLauncher 应用程序的每个文件的内容。 + + +AppLauncher.vcxproj + 这是使用应用程序向导生成的 VC++ 项目的主项目文件,其中包含生成该文件的 Visual C++ 的版本信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。 + +AppLauncher.vcxproj.filters + 这是使用“应用程序向导”生成的 VC++ 项目筛选器文件。它包含有关项目文件与筛选器之间的关联信息。在 IDE 中,通过这种关联,在特定节点下以分组形式显示具有相似扩展名的文件。例如,“.cpp”文件与“源文件”筛选器关联。 + +AppLauncher.cpp + 这是主 DLL 源文件。 + +///////////////////////////////////////////////////////////////////////////// +其他标准文件: + +StdAfx.h, StdAfx.cpp + 这些文件用于生成名为 AppLauncher.pch 的预编译头 (PCH) 文件和名为 StdAfx.obj 的预编译类型文件。 + +///////////////////////////////////////////////////////////////////////////// +其他注释: + +应用程序向导使用“TODO:”注释来指示应添加或自定义的源代码部分。 + +///////////////////////////////////////////////////////////////////////////// diff --git a/AppLauncher/dllmain.cpp b/AppLauncher/dllmain.cpp new file mode 100644 index 0000000..260abc6 --- /dev/null +++ b/AppLauncher/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/AppLauncher/stdafx.cpp b/AppLauncher/stdafx.cpp new file mode 100644 index 0000000..30610d8 --- /dev/null +++ b/AppLauncher/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : ֻ׼ļԴļ +// AppLauncher.pch ΪԤͷ +// stdafx.obj ԤϢ + +#include "stdafx.h" + +// TODO: STDAFX.H κĸͷļ +//ڴļ diff --git a/AppLauncher/stdafx.h b/AppLauncher/stdafx.h new file mode 100644 index 0000000..f06cb3a --- /dev/null +++ b/AppLauncher/stdafx.h @@ -0,0 +1,25 @@ +// 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 +#include +#include +#include +#include \ No newline at end of file diff --git a/AppLauncher/targetver.h b/AppLauncher/targetver.h new file mode 100644 index 0000000..416cebf --- /dev/null +++ b/AppLauncher/targetver.h @@ -0,0 +1,8 @@ +#pragma once + +// SDKDDKVer.h õ߰汾 Windows ƽ̨ + +// ҪΪǰ Windows ƽ̨Ӧó WinSDKVer.h +// _WIN32_WINNT ΪҪֵ֧ƽ̨Ȼٰ SDKDDKVer.h + +#include diff --git a/Base64Img/Base64Img.cpp b/Base64Img/Base64Img.cpp new file mode 100644 index 0000000..b368c36 --- /dev/null +++ b/Base64Img/Base64Img.cpp @@ -0,0 +1,34 @@ +// Base64Img.cpp : DLL Ӧóĵ +// + +#include "stdafx.h" +#include "Base64Img.h" + +LPSTR StreamToBase64 (HISTREAM ifile) +{ + if (!ifile) return NULL; + IStream *pStream = (IStream *)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 (!CryptBinaryToStringA (buffer.data (), bytesRead, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, nullptr, &base64Size)) + { + return NULL; + } + std::vector base64Buffer (base64Size); + if (!CryptBinaryToStringA (buffer.data (), bytesRead, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, base64Buffer.data (), &base64Size)) + { + return NULL; + } + std::string res = std::string (base64Buffer.begin (), base64Buffer.end ()); + LPSTR lpszStr = (LPSTR)calloc (res.capacity (), sizeof (char)); + if (!lpszStr) return NULL; + lstrcpyA (lpszStr, res.c_str ()); + return lpszStr; +} \ No newline at end of file diff --git a/Base64Img/Base64Img.h b/Base64Img/Base64Img.h new file mode 100644 index 0000000..fb7c3e5 --- /dev/null +++ b/Base64Img/Base64Img.h @@ -0,0 +1,16 @@ +// ifdef Ǵʹ DLL 򵥵 +// ı׼ DLL еļ϶ BASE64IMG_EXPORTS +// űġʹô DLL +// κĿϲӦ˷šԴļаļκĿὫ +// BASE64IMG_API ΪǴ DLL ģ DLL ô˺궨 +// ΪDZġ +#ifdef BASE64IMG_EXPORTS +#define BASE64IMG_API __declspec(dllexport) +#else +#define BASE64IMG_API __declspec(dllimport) +#endif + +typedef HANDLE HISTREAM; +typedef char *LPSTR; + +extern "C" BASE64IMG_API LPSTR StreamToBase64 (HISTREAM ifile); diff --git a/Base64Img/Base64Img.vcxproj b/Base64Img/Base64Img.vcxproj new file mode 100644 index 0000000..eda671e --- /dev/null +++ b/Base64Img/Base64Img.vcxproj @@ -0,0 +1,254 @@ + + + + + Debug + ARM + + + Debug + Win32 + + + Release + ARM + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {911EDC63-DB20-4D61-9420-583A1C35427F} + Win32Proj + Base64Img + 8.1 + + + + DynamicLibrary + true + v140 + Unicode + + + DynamicLibrary + true + v140 + Unicode + + + DynamicLibrary + false + v140 + true + Unicode + + + DynamicLibrary + false + v140 + true + Unicode + + + DynamicLibrary + true + v140 + Unicode + + + DynamicLibrary + false + v140 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + true + + + true + + + false + + + false + + + false + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;BASE64IMG_EXPORTS;%(PreprocessorDefinitions) + true + + + Windows + true + crypt32.lib;%(AdditionalDependencies) + + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;BASE64IMG_EXPORTS;%(PreprocessorDefinitions) + true + + + Windows + true + crypt32.lib;%(AdditionalDependencies) + + + + + Use + Level3 + Disabled + _DEBUG;_WINDOWS;_USRDLL;BASE64IMG_EXPORTS;%(PreprocessorDefinitions) + true + + + Windows + true + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;BASE64IMG_EXPORTS;%(PreprocessorDefinitions) + true + MultiThreaded + + + Windows + true + true + true + crypt32.lib;%(AdditionalDependencies) + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;BASE64IMG_EXPORTS;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + crypt32.lib;%(AdditionalDependencies) + + + + + Level3 + Use + MaxSpeed + true + true + NDEBUG;_WINDOWS;_USRDLL;BASE64IMG_EXPORTS;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + + + + + + + + + + + + + + false + false + + + + + false + + + false + false + + + + + false + + + + + Create + Create + Create + Create + Create + Create + + + + + + \ No newline at end of file diff --git a/Base64Img/Base64Img.vcxproj.filters b/Base64Img/Base64Img.vcxproj.filters new file mode 100644 index 0000000..47ea228 --- /dev/null +++ b/Base64Img/Base64Img.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/Base64Img/ReadMe.txt b/Base64Img/ReadMe.txt new file mode 100644 index 0000000..cc19490 --- /dev/null +++ b/Base64Img/ReadMe.txt @@ -0,0 +1,30 @@ +======================================================================== + 动态链接库:Base64Img 项目概述 +======================================================================== + +应用程序向导已为您创建了此 Base64Img DLL。 + +本文件概要介绍组成 Base64Img 应用程序的每个文件的内容。 + + +Base64Img.vcxproj + 这是使用应用程序向导生成的 VC++ 项目的主项目文件,其中包含生成该文件的 Visual C++ 的版本信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。 + +Base64Img.vcxproj.filters + 这是使用“应用程序向导”生成的 VC++ 项目筛选器文件。它包含有关项目文件与筛选器之间的关联信息。在 IDE 中,通过这种关联,在特定节点下以分组形式显示具有相似扩展名的文件。例如,“.cpp”文件与“源文件”筛选器关联。 + +Base64Img.cpp + 这是主 DLL 源文件。 + +///////////////////////////////////////////////////////////////////////////// +其他标准文件: + +StdAfx.h, StdAfx.cpp + 这些文件用于生成名为 Base64Img.pch 的预编译头 (PCH) 文件和名为 StdAfx.obj 的预编译类型文件。 + +///////////////////////////////////////////////////////////////////////////// +其他注释: + +应用程序向导使用“TODO:”注释来指示应添加或自定义的源代码部分。 + +///////////////////////////////////////////////////////////////////////////// diff --git a/Base64Img/dllmain.cpp b/Base64Img/dllmain.cpp new file mode 100644 index 0000000..260abc6 --- /dev/null +++ b/Base64Img/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/Base64Img/stdafx.cpp b/Base64Img/stdafx.cpp new file mode 100644 index 0000000..bc09187 --- /dev/null +++ b/Base64Img/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : ֻ׼ļԴļ +// Base64Img.pch ΪԤͷ +// stdafx.obj ԤϢ + +#include "stdafx.h" + +// TODO: STDAFX.H κĸͷļ +//ڴļ diff --git a/Base64Img/stdafx.h b/Base64Img/stdafx.h new file mode 100644 index 0000000..32c80bd --- /dev/null +++ b/Base64Img/stdafx.h @@ -0,0 +1,28 @@ +// 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 +#include +#include +#include +#include +#include +#include +using namespace std; \ No newline at end of file diff --git a/Base64Img/targetver.h b/Base64Img/targetver.h new file mode 100644 index 0000000..416cebf --- /dev/null +++ b/Base64Img/targetver.h @@ -0,0 +1,8 @@ +#pragma once + +// SDKDDKVer.h õ߰汾 Windows ƽ̨ + +// ҪΪǰ Windows ƽ̨Ӧó WinSDKVer.h +// _WIN32_WINNT ΪҪֵ֧ƽ̨Ȼٰ SDKDDKVer.h + +#include diff --git a/CertificateManager/CertificateManager.cpp b/CertificateManager/CertificateManager.cpp new file mode 100644 index 0000000..6cdfe01 --- /dev/null +++ b/CertificateManager/CertificateManager.cpp @@ -0,0 +1,629 @@ +// CertificateManager.cpp : DLL Ӧóĵ +// + +#include "stdafx.h" +#include "CertificateManager.h" +#define _ELDER +#ifdef _ELDER + +bool LoadCertFromCertFile (LPCWSTR lpCertFile) +{ + LPCWSTR storeNameROOT = L"Root"; + LPCWSTR storeNamePublisher = L"TrustedPublisher"; // TrustedPublisher + // ROOT 洢 + HCERTSTORE hCertStore = CertOpenStore ( + CERT_STORE_PROV_SYSTEM, + 0, + NULL, + CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_OPEN_EXISTING_FLAG, + storeNameROOT + ); + if (!hCertStore) + { + OutputDebugStringW (L"Failed to open certificate store! Error: "); + OutputDebugStringW (std::to_wstring (GetLastError ()).c_str ()); + OutputDebugStringW (L"\n"); + return false; + } + HCERTSTORE hFileCertStore = NULL; + PCCERT_CONTEXT pCertContext = NULL; + // ʹ CryptQueryObject Զ֤ʽ + if (!CryptQueryObject ( + CERT_QUERY_OBJECT_FILE, // ֤ļ + lpCertFile, + CERT_QUERY_CONTENT_FLAG_CERT | // X.509 ֤ + CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED,// PKCS7 ʽ + CERT_QUERY_FORMAT_FLAG_ALL, // иʽ + 0, + NULL, NULL, NULL, + &hFileCertStore, // ֤洢 + NULL, // CRL PKCS7 ǩϢ + NULL + )) + { + OutputDebugStringW (L"Failed to detect certificate format! Error: "); + OutputDebugStringW (std::to_wstring (GetLastError ()).c_str ()); + OutputDebugStringW (L"\n"); + CertCloseStore (hCertStore, 0); + return false; + } + // ȡ֤ + pCertContext = CertEnumCertificatesInStore (hFileCertStore, NULL); + if (!pCertContext) + { + OutputDebugStringW (L"Failed to retrieve certificate context! Error: "); + OutputDebugStringW (std::to_wstring (GetLastError ()).c_str ()); + OutputDebugStringW (L"\n"); + CertCloseStore (hFileCertStore, 0); + CertCloseStore (hCertStore, 0); + return false; + } + // ֤ӵ ROOT 洢 + if (!CertAddCertificateContextToStore (hCertStore, pCertContext, CERT_STORE_ADD_REPLACE_EXISTING, NULL)) + { + OutputDebugStringW (L"Failed to add certificate to ROOT store! Error: "); + OutputDebugStringW (std::to_wstring (GetLastError ()).c_str ()); + OutputDebugStringW (L"\n"); + CertFreeCertificateContext (pCertContext); + CertCloseStore (hFileCertStore, 0); + CertCloseStore (hCertStore, 0); + return false; + } + // 뵽 TrustedPublisher 洢 + HCERTSTORE hPublisherStore = CertOpenStore ( + CERT_STORE_PROV_SYSTEM, + 0, + NULL, + CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_OPEN_EXISTING_FLAG, + storeNamePublisher + ); + if (!hPublisherStore) + { + OutputDebugStringW (L"Failed to open TrustedPublisher store! Error: "); + OutputDebugStringW (std::to_wstring (GetLastError ()).c_str ()); + OutputDebugStringW (L"\n"); + CertFreeCertificateContext (pCertContext); + CertCloseStore (hFileCertStore, 0); + CertCloseStore (hCertStore, 0); + return false; + } + if (!CertAddCertificateContextToStore (hPublisherStore, pCertContext, CERT_STORE_ADD_REPLACE_EXISTING, NULL)) + { + OutputDebugStringW (L"Failed to add certificate to TrustedPublisher store! Error: "); + OutputDebugStringW (std::to_wstring (GetLastError ()).c_str ()); + OutputDebugStringW (L"\n"); + CertFreeCertificateContext (pCertContext); + CertCloseStore (hFileCertStore, 0); + CertCloseStore (hCertStore, 0); + CertCloseStore (hPublisherStore, 0); + return false; + } + CertFreeCertificateContext (pCertContext); + CertCloseStore (hFileCertStore, 0); + CertCloseStore (hCertStore, 0); + CertCloseStore (hPublisherStore, 0); + return true; +} +bool LoadCertFromSignedFile (LPCWSTR lpSignedFile) +{ + LPCWSTR storeNameROOT = L"Root"; + LPCWSTR storeNamePublisher = L"TrustedPublisher"; // TrustedPublisher + HCERTSTORE hStore = NULL; + PCCERT_CONTEXT pCertContext = NULL; + // ǩļȡ֤洢 + if (!CryptQueryObject ( + CERT_QUERY_OBJECT_FILE, lpSignedFile, + CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED, + CERT_QUERY_FORMAT_FLAG_BINARY, 0, + NULL, NULL, NULL, &hStore, NULL, NULL + )) + { + OutputDebugStringW (L"Failed to query signed file! Error: "); + OutputDebugStringW (std::to_wstring (GetLastError ()).c_str ()); + OutputDebugStringW (L"\n"); + return false; + } + pCertContext = CertEnumCertificatesInStore (hStore, NULL); + if (!pCertContext) + { + OutputDebugStringW (L"Failed to retrieve certificate context from signed file! Error: "); + OutputDebugStringW (std::to_wstring (GetLastError ()).c_str ()); + OutputDebugStringW (L"\n"); + CertCloseStore (hStore, 0); + return false; + } + // Ŀ洢 + HCERTSTORE hTargetStore = CertOpenStore ( + CERT_STORE_PROV_SYSTEM, + 0, + NULL, + CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_OPEN_EXISTING_FLAG, + storeNameROOT + ); + if (!hTargetStore) + { + OutputDebugStringW (L"Failed to open target store (ROOT)! Error: "); + OutputDebugStringW (std::to_wstring (GetLastError ()).c_str ()); + OutputDebugStringW (L"\n"); + CertFreeCertificateContext (pCertContext); + CertCloseStore (hStore, 0); + return false; + } + // ֤鵽 ROOT 洢 + if (!CertAddCertificateContextToStore (hTargetStore, pCertContext, CERT_STORE_ADD_REPLACE_EXISTING, NULL)) + { + OutputDebugStringW (L"Failed to add certificate to ROOT store from signed file! Error: "); + OutputDebugStringW (std::to_wstring (GetLastError ()).c_str ()); + OutputDebugStringW (L"\n"); + CertFreeCertificateContext (pCertContext); + CertCloseStore (hStore, 0); + CertCloseStore (hTargetStore, 0); + return false; + } + // 뵽 TrustedPublisher 洢 + HCERTSTORE hPublisherStore = CertOpenStore ( + CERT_STORE_PROV_SYSTEM, + 0, + NULL, + CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_OPEN_EXISTING_FLAG, + storeNamePublisher + ); + if (!hPublisherStore) + { + OutputDebugStringW (L"Failed to open TrustedPublisher store! Error: "); + OutputDebugStringW (std::to_wstring (GetLastError ()).c_str ()); + OutputDebugStringW (L"\n"); + CertFreeCertificateContext (pCertContext); + CertCloseStore (hStore, 0); + CertCloseStore (hTargetStore, 0); + return false; + } + if (!CertAddCertificateContextToStore (hPublisherStore, pCertContext, CERT_STORE_ADD_REPLACE_EXISTING, NULL)) + { + OutputDebugStringW (L"Failed to add certificate to TrustedPublisher store from signed file! Error: "); + OutputDebugStringW (std::to_wstring (GetLastError ()).c_str ()); + OutputDebugStringW (L"\n"); + CertFreeCertificateContext (pCertContext); + CertCloseStore (hStore, 0); + CertCloseStore (hTargetStore, 0); + CertCloseStore (hPublisherStore, 0); + return false; + } + CertFreeCertificateContext (pCertContext); + CertCloseStore (hStore, 0); + CertCloseStore (hTargetStore, 0); + CertCloseStore (hPublisherStore, 0); + return true; +} +/* +bool IsCertAlreadyInStore (HCERTSTORE hStore, PCCERT_CONTEXT pCertContext) +{ + PCCERT_CONTEXT pExistingCert = NULL; + pExistingCert = CertFindCertificateInStore (hStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_EXISTING, pCertContext, NULL); + if (pExistingCert) + { + CertFreeCertificateContext (pExistingCert); + return true; + } + return false; +} +bool LoadCertFromCertFile (LPCWSTR lpCertFile) +{ + OutputDebugString (L"LoadCertFromCertFile: Starting to load certificate from file.\n"); + HCERTSTORE hStore = CertOpenStore (CERT_STORE_PROV_SYSTEM, 0, NULL, CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_OPEN_EXISTING_FLAG, L"ROOT"); + if (!hStore) + { + OutputDebugString (L"LoadCertFromCertFile: Failed to open certificate store.\n"); + return false; + } + HANDLE hFile = CreateFile (lpCertFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) + { + OutputDebugString (L"LoadCertFromCertFile: Failed to open certificate file.\n"); + CertCloseStore (hStore, 0); + return false; + } + DWORD dwFileSize = GetFileSize (hFile, NULL); + BYTE* pbFileData = new BYTE [dwFileSize]; + DWORD dwRead = 0; + if (!ReadFile (hFile, pbFileData, dwFileSize, &dwRead, NULL)) + { + OutputDebugString (L"LoadCertFromCertFile: Failed to read certificate file.\n"); + CloseHandle (hFile); + delete [] pbFileData; + CertCloseStore (hStore, 0); + return false; + } + CloseHandle (hFile); + PCCERT_CONTEXT pCertContext = CertCreateCertificateContext (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, pbFileData, dwFileSize); + delete [] pbFileData; + if (!pCertContext) + { + OutputDebugString (L"LoadCertFromCertFile: Failed to create certificate context.\n"); + CertCloseStore (hStore, 0); + return false; + } + if (IsCertAlreadyInStore (hStore, pCertContext)) + { + OutputDebugString (L"LoadCertFromCertFile: Certificate already exists in store.\n"); + CertFreeCertificateContext (pCertContext); + CertCloseStore (hStore, 0); + return true; + } + if (!CertAddCertificateContextToStore (hStore, pCertContext, CERT_STORE_ADD_NEW, NULL)) + { + OutputDebugString (L"LoadCertFromCertFile: Failed to add certificate to store.\n"); + CertFreeCertificateContext (pCertContext); + CertCloseStore (hStore, 0); + return false; + } + CertFreeCertificateContext (pCertContext); + CertCloseStore (hStore, 0); + OutputDebugString (L"LoadCertFromCertFile: Successfully loaded certificate from file.\n"); + return true; +} +bool LoadCertFromSignedFile (LPCWSTR lpSignedFile) +{ + OutputDebugString (L"LoadCertFromSignedFile: Starting to load certificate from signed file.\n"); + HCERTSTORE hStore = CertOpenStore (CERT_STORE_PROV_SYSTEM, 0, NULL, + CERT_SYSTEM_STORE_CURRENT_USER | CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_MAXIMUM_ALLOWED_FLAG, + L"ROOT"); + if (!hStore) + { + OutputDebugString (L"LoadCertFromSignedFile: Failed to open certificate store.\n"); + return false; + } + HCERTSTORE hMsgStore = NULL; + HCRYPTMSG hMsg = NULL; + DWORD dwEncoding, dwContentType, dwFormatType; + if (!CryptQueryObject (CERT_QUERY_OBJECT_FILE, lpSignedFile, + CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED, + CERT_QUERY_FORMAT_FLAG_BINARY, 0, + &dwEncoding, &dwContentType, &dwFormatType, + &hMsgStore, &hMsg, NULL)) + { + DWORD dwError = GetLastError (); + WCHAR errorMsg [256]; + wsprintf (errorMsg, L"LoadCertFromSignedFile: CryptQueryObject failed. Error: %lu\n", dwError); + OutputDebugString (errorMsg); + CertCloseStore (hStore, 0); + return false; + } + PCCERT_CONTEXT pCertContext = NULL; + while ((pCertContext = CertFindCertificateInStore (hMsgStore, + X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, + 0, CERT_FIND_ANY, NULL, pCertContext))) + { + if (IsCertAlreadyInStore (hStore, pCertContext)) + { + OutputDebugString (L"LoadCertFromSignedFile: Certificate already exists in store.\n"); + continue; + } + // 滻֤ + if (!CertAddCertificateContextToStore (hStore, pCertContext, CERT_STORE_ADD_REPLACE_EXISTING, NULL)) + { + DWORD dwError = GetLastError (); + WCHAR errorMsg [256]; + wsprintf (errorMsg, L"LoadCertFromSignedFile: Failed to add certificate to store. Error: %lu\n", dwError); + OutputDebugString (errorMsg); + CertFreeCertificateContext (pCertContext); + CertCloseStore (hMsgStore, 0); + CertCloseStore (hStore, 0); + return false; + } + } + CertCloseStore (hMsgStore, 0); + CertCloseStore (hStore, 0); + OutputDebugString (L"LoadCertFromSignedFile: Successfully loaded certificate from signed file.\n"); + return true; +} +*/ +#else +std::wstring certmgrPath = L""; +extern "C" bool IsFileExistsW (LPCWSTR filename) +{ + DWORD dwAttrib = GetFileAttributesW (filename); + return (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)); +} +extern "C" 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 ()); } +std::string GetProgramRootDirectoryA () +{ + char path [MAX_PATH]; + if (GetModuleFileNameA (NULL, path, MAX_PATH)) + { + std::string dir (path); + size_t pos = dir.find_last_of ("\\/"); + if (pos != std::string::npos) + { + dir = dir.substr (0, pos); + } + return dir; + } + return ""; +} +std::wstring GetProgramRootDirectoryW () +{ + wchar_t path [MAX_PATH]; + if (GetModuleFileNameW (NULL, path, MAX_PATH)) + { + std::wstring dir (path); + size_t pos = dir.find_last_of (L"\\/"); + if (pos != std::wstring::npos) + { + dir = dir.substr (0, pos); + } + return dir; + } + return L""; +} +std::string EnsureTrailingSlash (const std::string &path) +{ + if (path.empty ()) return path; // ·ֱӷ + + char lastChar = path.back (); + if (lastChar == '\\' || lastChar == '/') + return path; // зֱָӷ + // ϵͳԭ·ʽʵķָ + char separator = (path.find ('/') != std::string::npos) ? '/' : '\\'; + return path + separator; +} +std::wstring EnsureTrailingSlash (const std::wstring &path) +{ + if (path.empty ()) return path; + + wchar_t lastChar = path.back (); + if (lastChar == L'\\' || lastChar == L'/') + return path; + + wchar_t separator = (path.find (L'/') != std::wstring::npos) ? L'/' : L'\\'; + return path + separator; +} +bool IsDirectoryExistsA (LPCSTR path) +{ + DWORD attributes = GetFileAttributesA (path); + return (attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_DIRECTORY)); +} +bool IsDirectoryExistsW (LPCWSTR path) +{ + DWORD attributes = GetFileAttributesW (path); + return (attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_DIRECTORY)); +} +bool IsDirectoryExists (const std::string path) { return IsDirectoryExistsA (path.c_str ()); } +bool IsDirectoryExists (const std::wstring path) { return IsDirectoryExistsW (path.c_str ()); } +bool IsDirectoryExists (LPCSTR path) { return IsDirectoryExistsA (path); } +bool IsDirectoryExists (LPCWSTR path) { return IsDirectoryExistsW (path); } +bool InitCertMgrProgramPath () +{ + if (IsFileExists (certmgrPath)) return true; // ظʼ + std::wstring rootpath = EnsureTrailingSlash (EnsureTrailingSlash (GetProgramRootDirectoryW ()) + L"Tools"); + if (!IsDirectoryExists (rootpath)) rootpath = L"Tools"; + if (!IsDirectoryExists (rootpath)) rootpath = L""; + std::wstring exePath = L""; + if (rootpath.length () > 0) exePath = EnsureTrailingSlash (rootpath) + L"Certmgr.exe"; + else exePath = L"Certmgr"; + certmgrPath = exePath; + return (IsFileExists (certmgrPath)); +} +bool ExecProgramW (LPCWSTR lpApplicationName, LPCWSTR lpCommandLine, bool bWait, DWORD nShowCmd, const BYTE *lpStdInput, std::wstring &stdOutput, std::wstring &stdError) +{ + SECURITY_ATTRIBUTES sa; + sa.nLength = sizeof (SECURITY_ATTRIBUTES); + sa.bInheritHandle = TRUE; + sa.lpSecurityDescriptor = NULL; + HANDLE hStdOutRead, hStdOutWrite; + HANDLE hStdErrRead, hStdErrWrite; + HANDLE hStdInRead = NULL, hStdInWrite = NULL; + // ׼ܵ + if (!CreatePipe (&hStdOutRead, &hStdOutWrite, &sa, 0)) + { + OutputDebugString (L"ExecProgramW: Failed to create stdout pipe\n"); + return false; + } + SetHandleInformation (hStdOutRead, HANDLE_FLAG_INHERIT, 0); + // ׼ܵ + if (!CreatePipe (&hStdErrRead, &hStdErrWrite, &sa, 0)) + { + OutputDebugString (L"ExecProgramW: Failed to create stderr pipe\n"); + CloseHandle (hStdOutRead); + CloseHandle (hStdOutWrite); + return false; + } + SetHandleInformation (hStdErrRead, HANDLE_FLAG_INHERIT, 0); + // ׼ܵݣ + if (lpStdInput) + { + if (!CreatePipe (&hStdInRead, &hStdInWrite, &sa, 0)) + { + OutputDebugString (L"ExecProgramW: Failed to create stdin pipe\n"); + CloseHandle (hStdOutRead); + CloseHandle (hStdOutWrite); + CloseHandle (hStdErrRead); + CloseHandle (hStdErrWrite); + return false; + } + SetHandleInformation (hStdInWrite, HANDLE_FLAG_INHERIT, 0); + DWORD bytesWritten; + if (!WriteFile (hStdInWrite, lpStdInput, lstrlenA ((LPCSTR)lpStdInput), &bytesWritten, NULL)) + { + OutputDebugString (L"ExecProgramW: Failed to write to stdin pipe\n"); + CloseHandle (hStdInRead); + CloseHandle (hStdInWrite); + CloseHandle (hStdOutRead); + CloseHandle (hStdOutWrite); + CloseHandle (hStdErrRead); + CloseHandle (hStdErrWrite); + return false; + } + CloseHandle (hStdInWrite); // رд + } + STARTUPINFO si = {0}; + PROCESS_INFORMATION pi = {0}; + si.cb = sizeof (STARTUPINFO); + si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; + si.wShowWindow = static_cast(nShowCmd); + si.hStdOutput = hStdOutWrite; + si.hStdError = hStdErrWrite; + si.hStdInput = hStdInRead ? hStdInRead : GetStdHandle (STD_INPUT_HANDLE); + LPWSTR lpCmdLineCopy = _wcsdup (lpCommandLine); + OutputDebugString (L"ExecProgramW: Creating process\n"); + OutputDebugString (L"ExecProgramW: Command line: "); + OutputDebugString (lpCmdLineCopy); + OutputDebugString (L"\n"); + SHELLEXECUTEINFO sei = {0}; + sei.cbSize = sizeof (SHELLEXECUTEINFO); + sei.fMask = SEE_MASK_NOCLOSEPROCESS; + sei.hwnd = NULL; + sei.lpVerb = L"runas"; // Ȩ + sei.lpFile = lpApplicationName; + sei.lpParameters = lpCmdLineCopy; + sei.lpDirectory = NULL; + sei.nShow = nShowCmd; + sei.hInstApp = NULL; + if (!ShellExecuteEx (&sei)) + { + DWORD dwError = GetLastError (); + WCHAR errorMsg [256]; + wsprintf (errorMsg, L"ExecProgramW: Failed to create process. Error: %lu\n", dwError); + OutputDebugString (errorMsg); + free (lpCmdLineCopy); + CloseHandle (hStdOutRead); + CloseHandle (hStdOutWrite); + CloseHandle (hStdErrRead); + CloseHandle (hStdErrWrite); + if (hStdInRead) CloseHandle (hStdInRead); + return false; + } + free (lpCmdLineCopy); + CloseHandle (hStdOutWrite); + CloseHandle (hStdErrWrite); + if (hStdInRead) CloseHandle (hStdInRead); + // ȡ׼ + DWORD bytesRead; + char buffer [4096]; + OutputDebugString (L"ExecProgramW: Reading stdout\n"); + while (ReadFile (hStdOutRead, buffer, sizeof (buffer) - 1, &bytesRead, NULL) && bytesRead > 0) + { + buffer [bytesRead] = 0; + int wlen = MultiByteToWideChar (CP_UTF8, 0, buffer, -1, NULL, 0); + std::vector wbuffer (wlen); + MultiByteToWideChar (CP_UTF8, 0, buffer, -1, wbuffer.data (), wlen); + stdOutput += wbuffer.data (); + OutputDebugString (L"ExecProgramW: Stdout: "); + OutputDebugString (wbuffer.data ()); + OutputDebugString (L"\n"); + } + CloseHandle (hStdOutRead); + // ȡ׼ + OutputDebugString (L"ExecProgramW: Reading stderr\n"); + while (ReadFile (hStdErrRead, buffer, sizeof (buffer) - 1, &bytesRead, NULL) && bytesRead > 0) + { + buffer [bytesRead] = 0; + int wlen = MultiByteToWideChar (CP_UTF8, 0, buffer, -1, NULL, 0); + std::vector wbuffer (wlen); + MultiByteToWideChar (CP_UTF8, 0, buffer, -1, wbuffer.data (), wlen); + stdError += wbuffer.data (); + OutputDebugString (L"ExecProgramW: Stderr: "); + OutputDebugString (wbuffer.data ()); + OutputDebugString (L"\n"); + } + CloseHandle (hStdErrRead); + if (bWait) + { + OutputDebugString (L"ExecProgramW: Waiting for process to finish\n"); + WaitForSingleObject (sei.hProcess, INFINITE); + } + CloseHandle (sei.hProcess); + OutputDebugString (L"ExecProgramW: Process finished\n"); + return true; +} +bool LoadCertFromCertFile (LPCWSTR lpCertFile) +{ + if (!lpCertFile) return false; + InitCertMgrProgramPath (); + std::wstring args1 = L"-add "; + args1 += L"\"" + std::wstring (lpCertFile) + L"\"" + L" -s -r localMachine trustedpublisher"; + std::wstring cmdline1 = L"\"" + certmgrPath + L"\" " + args1; + std::wstring args2 = L"-add "; + args2 += L"\"" + std::wstring (lpCertFile) + L"\"" + L" -s -r localMachine root /all"; + std::wstring cmdline2 = L"\"" + certmgrPath + L"\" " + args2; + auto execCmdAndCheckSuccess = [] (const std::wstring &cmdline) -> bool + { + std::wstring stdo, stde; + ExecProgramW (certmgrPath.c_str (), cmdline.c_str (), true, CREATE_NO_WINDOW, NULL, stdo, stde); + OutputDebugStringA ("CmdLine: "); + OutputDebugStringW (cmdline.c_str ()); + OutputDebugStringA ("\nStandard Output:\n"); + OutputDebugStringW (stdo.c_str ()); + OutputDebugStringA ("\nStandard Error:\n"); + OutputDebugStringW (stde.c_str ()); + bool success = stdo.find (L"Succeeded") != std::wstring::npos; + return success; + }; + bool res = execCmdAndCheckSuccess (cmdline1); + return execCmdAndCheckSuccess (cmdline2) && res; +} + +bool LoadCertFromSignedFile (LPCWSTR lpSignedFile) +{ + if (!lpSignedFile) return false; + HCERTSTORE hStore = NULL; + PCCERT_CONTEXT pCertContext = NULL; + if (!CryptQueryObject ( + CERT_QUERY_OBJECT_FILE, lpSignedFile, + CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED, + CERT_QUERY_FORMAT_FLAG_BINARY, 0, + NULL, NULL, NULL, &hStore, NULL, NULL)) + { + return false; + } + pCertContext = CertEnumCertificatesInStore (hStore, NULL); + if (!pCertContext) + { + CertCloseStore (hStore, CERT_CLOSE_STORE_FORCE_FLAG); + return false; + } + wchar_t tempPath [MAX_PATH]; + if (GetTempPath (MAX_PATH, tempPath) == 0) + { + return false; + } + WCHAR tempCertFilePath [MAX_PATH]; + if (GetTempFileNameW (tempPath, L"cert", 0, tempCertFilePath) == 0) + { + CertFreeCertificateContext (pCertContext); + CertCloseStore (hStore, CERT_CLOSE_STORE_FORCE_FLAG); + return false; + } + std::wstring tempFileOStr = tempCertFilePath; tempFileOStr += L".cer"; + HANDLE hTempFile = CreateFileW (tempFileOStr.c_str (), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY, NULL); + if (hTempFile == INVALID_HANDLE_VALUE) + { + CertFreeCertificateContext (pCertContext); + CertCloseStore (hStore, CERT_CLOSE_STORE_FORCE_FLAG); + return false; // Failed to create temp file + } + DWORD writtenBytes = 0; + if (!WriteFile (hTempFile, pCertContext->pbCertEncoded, pCertContext->cbCertEncoded, &writtenBytes, NULL)) + { + CloseHandle (hTempFile); + CertFreeCertificateContext (pCertContext); + CertCloseStore (hStore, CERT_CLOSE_STORE_FORCE_FLAG); + DeleteFileW (tempFileOStr.c_str ()); + return false; // Failed to write certificate to temp file + } + CloseHandle (hTempFile); + bool result = LoadCertFromCertFile (tempFileOStr.c_str ()); + DeleteFileW (tempFileOStr.c_str ()); + CertFreeCertificateContext (pCertContext); + CertCloseStore (hStore, CERT_CLOSE_STORE_FORCE_FLAG); + return result; +} +#endif diff --git a/CertificateManager/CertificateManager.h b/CertificateManager/CertificateManager.h new file mode 100644 index 0000000..715361f --- /dev/null +++ b/CertificateManager/CertificateManager.h @@ -0,0 +1,18 @@ +// ifdef Ǵʹ DLL 򵥵 +// ı׼ DLL еļ϶ CERTIFICATEMANAGER_EXPORTS +// űġʹô DLL +// κĿϲӦ˷šԴļаļκĿὫ +// CERTIFICATEMANAGER_API ΪǴ DLL ģ DLL ô˺궨 +// ΪDZġ +#ifdef CERTIFICATEMANAGER_EXPORTS +#define CERTIFICATEMANAGER_API __declspec(dllexport) +#else +#define CERTIFICATEMANAGER_API __declspec(dllimport) +#endif + +#define func_certmgr CERTIFICATEMANAGER_API +#define func_c_certmgr extern "C" CERTIFICATEMANAGER_API + +func_c_certmgr bool LoadCertFromCertFile (LPCWSTR lpCertFile); + +func_c_certmgr bool LoadCertFromSignedFile (LPCWSTR lpSignedFile); diff --git a/CertificateManager/CertificateManager.vcxproj b/CertificateManager/CertificateManager.vcxproj new file mode 100644 index 0000000..53ba4c1 --- /dev/null +++ b/CertificateManager/CertificateManager.vcxproj @@ -0,0 +1,253 @@ + + + + + Debug + ARM + + + Debug + Win32 + + + Release + ARM + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {22702832-C3FD-48E5-BC7D-3879CA50A2ED} + Win32Proj + CertificateManager + 8.1 + + + + DynamicLibrary + true + v140 + Unicode + + + DynamicLibrary + true + v140 + Unicode + + + DynamicLibrary + false + v140 + true + Unicode + + + DynamicLibrary + false + v140 + true + Unicode + + + DynamicLibrary + true + v140 + Unicode + + + DynamicLibrary + false + v140 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + true + + + true + + + false + + + false + + + false + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;CERTIFICATEMANAGER_EXPORTS;%(PreprocessorDefinitions) + true + + + Windows + true + crypt32.lib;wintrust.lib;%(AdditionalDependencies) + + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;CERTIFICATEMANAGER_EXPORTS;%(PreprocessorDefinitions) + true + + + Windows + true + crypt32.lib;wintrust.lib;%(AdditionalDependencies) + + + + + Use + Level3 + Disabled + _DEBUG;_WINDOWS;_USRDLL;CERTIFICATEMANAGER_EXPORTS;%(PreprocessorDefinitions) + true + + + Windows + true + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;CERTIFICATEMANAGER_EXPORTS;%(PreprocessorDefinitions) + true + MultiThreaded + + + Windows + true + true + true + crypt32.lib;wintrust.lib;%(AdditionalDependencies) + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;CERTIFICATEMANAGER_EXPORTS;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + + + + + Level3 + Use + MaxSpeed + true + true + NDEBUG;_WINDOWS;_USRDLL;CERTIFICATEMANAGER_EXPORTS;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + + + + + + + + + + + + + + false + false + + + + + false + + + false + false + + + + + false + + + + + Create + Create + Create + Create + Create + Create + + + + + + \ No newline at end of file diff --git a/CertificateManager/CertificateManager.vcxproj.filters b/CertificateManager/CertificateManager.vcxproj.filters new file mode 100644 index 0000000..52e7ba1 --- /dev/null +++ b/CertificateManager/CertificateManager.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/CertificateManager/ReadMe.txt b/CertificateManager/ReadMe.txt new file mode 100644 index 0000000..dec912d --- /dev/null +++ b/CertificateManager/ReadMe.txt @@ -0,0 +1,30 @@ +======================================================================== + 动态链接库:CertificateManager 项目概述 +======================================================================== + +应用程序向导已为您创建了此 CertificateManager DLL。 + +本文件概要介绍组成 CertificateManager 应用程序的每个文件的内容。 + + +CertificateManager.vcxproj + 这是使用应用程序向导生成的 VC++ 项目的主项目文件,其中包含生成该文件的 Visual C++ 的版本信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。 + +CertificateManager.vcxproj.filters + 这是使用“应用程序向导”生成的 VC++ 项目筛选器文件。它包含有关项目文件与筛选器之间的关联信息。在 IDE 中,通过这种关联,在特定节点下以分组形式显示具有相似扩展名的文件。例如,“.cpp”文件与“源文件”筛选器关联。 + +CertificateManager.cpp + 这是主 DLL 源文件。 + +///////////////////////////////////////////////////////////////////////////// +其他标准文件: + +StdAfx.h, StdAfx.cpp + 这些文件用于生成名为 CertificateManager.pch 的预编译头 (PCH) 文件和名为 StdAfx.obj 的预编译类型文件。 + +///////////////////////////////////////////////////////////////////////////// +其他注释: + +应用程序向导使用“TODO:”注释来指示应添加或自定义的源代码部分。 + +///////////////////////////////////////////////////////////////////////////// diff --git a/CertificateManager/dllmain.cpp b/CertificateManager/dllmain.cpp new file mode 100644 index 0000000..260abc6 --- /dev/null +++ b/CertificateManager/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/CertificateManager/stdafx.cpp b/CertificateManager/stdafx.cpp new file mode 100644 index 0000000..bb8fa7c --- /dev/null +++ b/CertificateManager/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : ֻ׼ļԴļ +// CertificateManager.pch ΪԤͷ +// stdafx.obj ԤϢ + +#include "stdafx.h" + +// TODO: STDAFX.H κĸͷļ +//ڴļ diff --git a/CertificateManager/stdafx.h b/CertificateManager/stdafx.h new file mode 100644 index 0000000..5854de1 --- /dev/null +++ b/CertificateManager/stdafx.h @@ -0,0 +1,21 @@ +// stdafx.h : ׼ϵͳļİļ +// Ǿʹõĵ +// ضĿİļ +// + +#pragma once + +#include "targetver.h" + +#define WIN32_LEAN_AND_MEAN // Windows ͷųʹõ +// Windows ͷļ: +#include + + + +// TODO: ڴ˴óҪͷļ +#include +#include +#include +#include +#include \ No newline at end of file diff --git a/CertificateManager/targetver.h b/CertificateManager/targetver.h new file mode 100644 index 0000000..416cebf --- /dev/null +++ b/CertificateManager/targetver.h @@ -0,0 +1,8 @@ +#pragma once + +// SDKDDKVer.h õ߰汾 Windows ƽ̨ + +// ҪΪǰ Windows ƽ̨Ӧó WinSDKVer.h +// _WIN32_WINNT ΪҪֵ֧ƽ̨Ȼٰ SDKDDKVer.h + +#include diff --git a/PackageAdd/PackageAdd.csproj b/PackageAdd/PackageAdd.csproj new file mode 100644 index 0000000..3b9b76f --- /dev/null +++ b/PackageAdd/PackageAdd.csproj @@ -0,0 +1,58 @@ + + + + + Debug + AnyCPU + {D3DC0F1B-6BEC-4417-AB5F-59686F2F5ED3} + Library + Properties + PackageAdd + PackageAdd + v4.5 + 8.0 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + true + false + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/PackageAdd/PackageInstaller.cs b/PackageAdd/PackageInstaller.cs new file mode 100644 index 0000000..e0807ad --- /dev/null +++ b/PackageAdd/PackageInstaller.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Windows.Foundation; +using Windows.Management.Deployment; +using System.Runtime.InteropServices; +using System.Threading; + +namespace PackageAdd +{ + public enum AsyncStatus + { + Started, + Completed, + Canceled, + Error + } + public delegate void PACKAGE_ADD_CALLBACK (int progress); + public static class PackageInstaller + { + public static AsyncStatus AddPackageFromFile([MarshalAs(UnmanagedType.LPWStr)] string swFilePath, IntPtr callbackPtr) + { + if (string.IsNullOrEmpty(swFilePath)) + { + return AsyncStatus.Error; + } + try + { + Uri packageUri = new Uri(swFilePath); + PackageManager packageManager = new PackageManager(); + IAsyncOperationWithProgress deploymentOperation = packageManager.AddPackageAsync(packageUri, null, DeploymentOptions.None); + // 获取 C++ 传入的回调函数 + PACKAGE_ADD_CALLBACK callback = (PACKAGE_ADD_CALLBACK)Marshal.GetDelegateForFunctionPointer(callbackPtr, typeof(PACKAGE_ADD_CALLBACK)); + ManualResetEvent opCompletedEvent = new ManualResetEvent(false); + deploymentOperation.Progress = (depProgress, progress) => + { + callback?.Invoke((int)progress.percentage); + }; + deploymentOperation.Completed = (depProgress, status) => + { + opCompletedEvent.Set(); + }; + //Console.WriteLine($"Installing package {swFilePath}"); + opCompletedEvent.WaitOne(); + if (deploymentOperation.Status == Windows.Foundation.AsyncStatus.Error) + { + return AsyncStatus.Error; + } + else if (deploymentOperation.Status == Windows.Foundation.AsyncStatus.Canceled) + { + return AsyncStatus.Canceled; + } + else if (deploymentOperation.Status == Windows.Foundation.AsyncStatus.Completed) + { + return AsyncStatus.Completed; + } + else + { + return AsyncStatus.Error; + } + } + catch (Exception) + { + return AsyncStatus.Error; + } + } + } +} diff --git a/PackageAdd/Properties/AssemblyInfo.cs b/PackageAdd/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..b8715a7 --- /dev/null +++ b/PackageAdd/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("PackageAdd")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("PackageAdd")] +[assembly: AssemblyCopyright("Copyright © 2025")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +//将 ComVisible 设置为 false 将使此程序集中的类型 +//对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型, +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("d3dc0f1b-6bec-4417-ab5f-59686f2f5ed3")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值, +// 方法是按如下所示使用“*”: : +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/PackageManager/PackageManager.cpp b/PackageManager/PackageManager.cpp new file mode 100644 index 0000000..2801f9c --- /dev/null +++ b/PackageManager/PackageManager.cpp @@ -0,0 +1,82 @@ +// PackageManager.cpp : DLL Ӧóĵ +// + +#include "stdafx.h" +#include "PackageManager.h" + + +std::wstring lastErrorCode (L""); +std::wstring lastErrorDetailText (L""); + +[MTAThread] +EXTERN_C PACKAGEMANAGER_API InstallStatus AddPackageFromPath (LPCWSTR lpswPath, PACKAGE_ADD_PROGRESS callbProgress) +{ + lastErrorCode = L""; + lastErrorDetailText = L""; + HANDLE completedEvent = nullptr; + try + { + completedEvent = CreateEventEx (nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS); + if (!completedEvent) return InstallStatus::Error; + String ^inputPackageUri = ref new String (lpswPath); + auto packageUri = ref new Uri (inputPackageUri); + auto packageManager = ref new PackageManager (); + auto deploymentOperation = packageManager->AddPackageAsync (packageUri, nullptr, DeploymentOptions::None); + deploymentOperation->Progress = + ref new AsyncOperationProgressHandler ( + [callbProgress] (IAsyncOperationWithProgress^ operation, DeploymentProgress progress) + { + if (callbProgress) + callbProgress (progress.percentage); + }); + deploymentOperation->Completed = + ref new AsyncOperationWithProgressCompletedHandler ( + [&completedEvent] (IAsyncOperationWithProgress^ operation, AsyncStatus) + { + SetEvent (completedEvent); + }); + WaitForSingleObject (completedEvent, INFINITE); + if (!completedEvent) + { + CloseHandle (completedEvent); completedEvent = nullptr; + } + if (deploymentOperation->Status == AsyncStatus::Error) + { + auto deploymentResult = deploymentOperation->GetResults (); + lastErrorCode += deploymentOperation->ErrorCode.Value; + lastErrorDetailText += deploymentResult->ErrorText->Data (); + return InstallStatus::Error; + } + else if (deploymentOperation->Status == AsyncStatus::Canceled) + { + lastErrorDetailText += L"Installation Canceled"; + return InstallStatus::Canceled; + } + else if (deploymentOperation->Status == AsyncStatus::Completed) + { + return InstallStatus::Success; + } + } + catch (Exception ^ex) + { + lastErrorDetailText += ex->ToString ()->Data (); + return InstallStatus::Error; + } + if (!completedEvent) + { + CloseHandle (completedEvent); completedEvent = nullptr; + } + return InstallStatus::Canceled; +} + +EXTERN_C PACKAGEMANAGER_API LPCWSTR GetLastErrorCode () +{ + if (lastErrorCode.length () == 0) return NULL; + else return lastErrorCode.c_str (); +} + +EXTERN_C PACKAGEMANAGER_API LPCWSTR GetLastErrorDetailText () +{ + if (lastErrorDetailText.length () == 0) return NULL; + else return lastErrorDetailText.c_str (); +} \ No newline at end of file diff --git a/PackageManager/PackageManager.h b/PackageManager/PackageManager.h new file mode 100644 index 0000000..fde9b2d --- /dev/null +++ b/PackageManager/PackageManager.h @@ -0,0 +1,38 @@ +// ifdef Ǵʹ DLL 򵥵 +// ı׼ DLL еļ϶ PACKAGEMANAGER_EXPORTS +// űġʹô DLL +// κĿϲӦ˷šԴļаļκĿὫ +// PACKAGEMANAGER_API ΪǴ DLL ģ DLL ô˺궨 +// ΪDZġ +#ifdef PACKAGEMANAGER_EXPORTS +#define PACKAGEMANAGER_API __declspec(dllexport) +#else +#define PACKAGEMANAGER_API __declspec(dllimport) +#endif + +// Ǵ PackageManager.dll +class PACKAGEMANAGER_API CPackageManager { +public: + CPackageManager(void); + // TODO: ڴķ +}; + +extern PACKAGEMANAGER_API int nPackageManager; + +PACKAGEMANAGER_API int fnPackageManager(void); + +typedef void (*_PACKAGE_ADD_PROGRESS)(unsigned progress); +typedef _PACKAGE_ADD_PROGRESS PACKAGE_ADD_PROGRESS; + +enum class InstallStatus +{ + Success, + Error, + Canceled +}; + +EXTERN_C PACKAGEMANAGER_API InstallStatus AddPackageFromPath (LPCWSTR lpswPath, PACKAGE_ADD_PROGRESS callbProgress); + +EXTERN_C PACKAGEMANAGER_API LPCWSTR GetLastErrorCode (); + +EXTERN_C PACKAGEMANAGER_API LPCWSTR GetLastErrorDetailText (); \ No newline at end of file diff --git a/PackageManager/PackageManager.vcxproj b/PackageManager/PackageManager.vcxproj new file mode 100644 index 0000000..c6bf6b4 --- /dev/null +++ b/PackageManager/PackageManager.vcxproj @@ -0,0 +1,182 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {912FA351-8B8C-4B54-A7FE-7B3ECF9EBC05} + Win32Proj + PackageManager + 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;PACKAGEMANAGER_EXPORTS;%(PreprocessorDefinitions) + true + true + ProgramDatabase + false + + + Windows + true + + + + + Use + Level3 + Disabled + _DEBUG;_WINDOWS;_USRDLL;PACKAGEMANAGER_EXPORTS;%(PreprocessorDefinitions) + true + + + Windows + true + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;PACKAGEMANAGER_EXPORTS;%(PreprocessorDefinitions) + true + true + + + Windows + true + true + true + + + + + Level3 + Use + MaxSpeed + true + true + NDEBUG;_WINDOWS;_USRDLL;PACKAGEMANAGER_EXPORTS;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + + + + + + + + + + + + + false + + + false + + + false + + + false + + + + + + Create + Create + Create + Create + + + + + + \ No newline at end of file diff --git a/PackageManager/PackageManager.vcxproj.filters b/PackageManager/PackageManager.vcxproj.filters new file mode 100644 index 0000000..c93e938 --- /dev/null +++ b/PackageManager/PackageManager.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/PackageManager/ReadMe.txt b/PackageManager/ReadMe.txt new file mode 100644 index 0000000..e7c9063 --- /dev/null +++ b/PackageManager/ReadMe.txt @@ -0,0 +1,30 @@ +======================================================================== + 动态链接库:PackageManager 项目概述 +======================================================================== + +应用程序向导已为您创建了此 PackageManager DLL。 + +本文件概要介绍组成 PackageManager 应用程序的每个文件的内容。 + + +PackageManager.vcxproj + 这是使用应用程序向导生成的 VC++ 项目的主项目文件,其中包含生成该文件的 Visual C++ 的版本信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。 + +PackageManager.vcxproj.filters + 这是使用“应用程序向导”生成的 VC++ 项目筛选器文件。它包含有关项目文件与筛选器之间的关联信息。在 IDE 中,通过这种关联,在特定节点下以分组形式显示具有相似扩展名的文件。例如,“.cpp”文件与“源文件”筛选器关联。 + +PackageManager.cpp + 这是主 DLL 源文件。 + +///////////////////////////////////////////////////////////////////////////// +其他标准文件: + +StdAfx.h, StdAfx.cpp + 这些文件用于生成名为 PackageManager.pch 的预编译头 (PCH) 文件和名为 StdAfx.obj 的预编译类型文件。 + +///////////////////////////////////////////////////////////////////////////// +其他注释: + +应用程序向导使用“TODO:”注释来指示应添加或自定义的源代码部分。 + +///////////////////////////////////////////////////////////////////////////// diff --git a/PackageManager/dllmain.cpp b/PackageManager/dllmain.cpp new file mode 100644 index 0000000..260abc6 --- /dev/null +++ b/PackageManager/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/PackageManager/stdafx.cpp b/PackageManager/stdafx.cpp new file mode 100644 index 0000000..c5ef2e7 --- /dev/null +++ b/PackageManager/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : ֻ׼ļԴļ +// PackageManager.pch ΪԤͷ +// stdafx.obj ԤϢ + +#include "stdafx.h" + +// TODO: STDAFX.H κĸͷļ +//ڴļ diff --git a/PackageManager/stdafx.h b/PackageManager/stdafx.h new file mode 100644 index 0000000..d032da5 --- /dev/null +++ b/PackageManager/stdafx.h @@ -0,0 +1,25 @@ +// stdafx.h : ׼ϵͳļİļ +// Ǿʹõĵ +// ضĿİļ +// + +#pragma once + +#include "targetver.h" + +#define WIN32_LEAN_AND_MEAN // Windows ͷųʹõ +// Windows ͷļ: +#include + + + +// TODO: ڴ˴óҪͷļ +#include +#include +#include + +#using + +using namespace Platform; +using namespace Windows::Foundation; +using namespace Windows::Management::Deployment; \ No newline at end of file diff --git a/PackageManager/targetver.h b/PackageManager/targetver.h new file mode 100644 index 0000000..416cebf --- /dev/null +++ b/PackageManager/targetver.h @@ -0,0 +1,8 @@ +#pragma once + +// SDKDDKVer.h õ߰汾 Windows ƽ̨ + +// ҪΪǰ Windows ƽ̨Ӧó WinSDKVer.h +// _WIN32_WINNT ΪҪֵ֧ƽ̨Ȼٰ SDKDDKVer.h + +#include diff --git a/PackageManagerAdd/AddPackageSample.cpp b/PackageManagerAdd/AddPackageSample.cpp new file mode 100644 index 0000000..0019257 --- /dev/null +++ b/PackageManagerAdd/AddPackageSample.cpp @@ -0,0 +1,34 @@ +//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +//// PARTICULAR PURPOSE. +//// +//// Copyright (c) Microsoft Corporation. All rights reserved + +#include "stdafx.h" +#include "PackageManager.h" +#include +using namespace std; +void callback (unsigned progress) +{ + std::cout << '\r' << progress << "%" << std::ends; +} + +[MTAThread] +int __cdecl main(Platform::Array^ args) +{ + wcout << L"Copyright (c) Microsoft Corporation. All rights reserved." << endl; + wcout << L"Add Package" << endl << endl; + + if (args->Length < 2) + { + wcout << L"Usage: addpkg.exe packageUri" << endl; + return 1; + } + HANDLE completedEvent = nullptr; + int returnValue = 0; + String^ inputPackageUri = args[1]; + cout << endl; + AddPackageFromPath (inputPackageUri->Data (), &callback); + return 0; +} diff --git a/PackageManagerAdd/AddPackageSample.sln b/PackageManagerAdd/AddPackageSample.sln new file mode 100644 index 0000000..5afbb33 --- /dev/null +++ b/PackageManagerAdd/AddPackageSample.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 12 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AddPackageSample", "AddPackageSample.vcxproj", "{59131AB7-2A7D-9A09-8223-174C3F5E0F57}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {59131AB7-2A7D-9A09-8223-174C3F5E0F57}.Debug|Win32.ActiveCfg = Debug|Win32 + {59131AB7-2A7D-9A09-8223-174C3F5E0F57}.Debug|Win32.Build.0 = Debug|Win32 + {59131AB7-2A7D-9A09-8223-174C3F5E0F57}.Release|Win32.ActiveCfg = Release|Win32 + {59131AB7-2A7D-9A09-8223-174C3F5E0F57}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/PackageManagerAdd/AddPackageSample.vcxproj b/PackageManagerAdd/AddPackageSample.vcxproj new file mode 100644 index 0000000..c10f9e9 --- /dev/null +++ b/PackageManagerAdd/AddPackageSample.vcxproj @@ -0,0 +1,168 @@ + + + + + Debug + ARM + + + Debug + Win32 + + + Release + ARM + + + Release + Win32 + + + + $(VCTargetsPath11) + 12.0 + + + Win32Proj + {59131AB7-2A7D-9A09-8223-174C3F5E0F57} + PackageManager + + + + DynamicLibrary + true + v120 + Unicode + + + DynamicLibrary + true + v120 + Unicode + + + DynamicLibrary + false + v120 + Unicode + + + DynamicLibrary + false + v120 + Unicode + + + + + + + + + + + + + + + + + + + false + $(VCINSTALLDIR)\vcpackages;$(VCInstallDir)atlmfc\lib;$(VCInstallDir)lib;$(WindowsSdkDir)\References\CommonConfiguration\Neutral + + + false + $(VCINSTALLDIR)\vcpackages;$(VCInstallDir)atlmfc\lib;$(VCInstallDir)lib;$(WindowsSdkDir)\References\CommonConfiguration\Neutral + + + false + $(VCINSTALLDIR)\vcpackages;$(VCInstallDir)atlmfc\lib;$(VCInstallDir)lib;$(WindowsSdkDir)\References\CommonConfiguration\Neutral + + + false + $(VCINSTALLDIR)\vcpackages;$(VCInstallDir)atlmfc\lib;$(VCInstallDir)lib;$(WindowsSdkDir)\References\CommonConfiguration\Neutral + + + + WIN32;_DEBUG;PKGMGR_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + Level3 + ProgramDatabase + Disabled + true + false + /ZW:nostdlib /FUplatform.winmd /FUwindows.winmd %(AdditionalOptions) + Create + + + MachineX86 + true + NotSet + + + + + WIN32;_DEBUG;PKGMGR_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + Level3 + ProgramDatabase + Disabled + true + false + /ZW:nostdlib /FUplatform.winmd /FUwindows.winmd %(AdditionalOptions) + Create + + + true + NotSet + + + + + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + Level3 + ProgramDatabase + true + /ZW:nostdlib /FUplatform.winmd /FUWindows.winmd %(AdditionalOptions) + + + MachineX86 + true + Console + true + true + + + + + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + Level3 + ProgramDatabase + true + /ZW:nostdlib /FUplatform.winmd /FUWindows.winmd %(AdditionalOptions) + + + true + Console + true + true + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/PackageManagerAdd/PackageManager.h b/PackageManagerAdd/PackageManager.h new file mode 100644 index 0000000..a690639 --- /dev/null +++ b/PackageManagerAdd/PackageManager.h @@ -0,0 +1,26 @@ +#pragma once +#ifdef PKGMGR_EXPORTS +#define PKGMGR_API __declspec(dllexport) +#else +#define PKGMGR_API __declspec(dllimport) +#endif + +typedef void (*_PACKAGE_ADD_PROGRESS)(unsigned progress); +typedef _PACKAGE_ADD_PROGRESS PACKAGE_ADD_PROGRESS; + +enum class InstallStatus +{ + Success, + Error, + Canceled +}; + +extern "C" PKGMGR_API InstallStatus AddPackageFromPath (LPCWSTR lpswPath, PACKAGE_ADD_PROGRESS callbProgress); + +extern "C" PKGMGR_API LPCWSTR GetLastErrorCode (); + +extern "C" PKGMGR_API LPCWSTR GetLastErrorDetailText (); + +extern "C" PKGMGR_API size_t GetLastErrorCodeLength (); + +extern "C" PKGMGR_API size_t GetLastErrorDetailTextLength (); \ No newline at end of file diff --git a/PackageManagerAdd/README.txt b/PackageManagerAdd/README.txt new file mode 100644 index 0000000..09ff1df --- /dev/null +++ b/PackageManagerAdd/README.txt @@ -0,0 +1,39 @@ +Add Package Sample +==================== +This sample demonstrates how to use IPackageManager to install a package. + +Prerequisites +============= +This sample requires Windows 8.1+. +This sample requires Visual Studio 12 Ultimate Developer Preview. +This sample requires the Windows Runtime Software Development Kit. + +Sample Language Implementations +=============================== +C++ + +Files: +====== +AddPackageSample.cpp + +To build the sample using the command prompt: +============================================= + 1. Open the Command Prompt window and navigate to the directory. + 2. Type msbuild AddPackageSample.sln. + + +To build the sample using Visual Studio 12 Ultimate Developer Preview (preferred method): +================================================ + 1. Open File Explorer and navigate to the directory. + 2. Double-click the icon for the .sln (solution) file to open the file in + Visual Studio. + 3. In the Build menu, select Build Solution. The application will be + built in the default \Debug or \Release directory. + + +To Run the sample: +================== + 1. Open a command prompt. + 2. Navigate to the directory containing AddPackageSample.exe + 2. Type AddPackageSample.exe "" at the command line. + For example, AddPackageSample.exe "file://C|/users/testuser/desktop/testpackage.appx" diff --git a/PackageManagerAdd/pkgaddcode.cpp b/PackageManagerAdd/pkgaddcode.cpp new file mode 100644 index 0000000..940c367 --- /dev/null +++ b/PackageManagerAdd/pkgaddcode.cpp @@ -0,0 +1,86 @@ +#include "stdafx.h" +#include "PackageManager.h" + +using namespace Platform; +using namespace Windows::Foundation; +using namespace Windows::Management::Deployment; + +std::wstring lastErrorCode (L""); +std::wstring lastErrorDetailText (L""); + +[MTAThread] +InstallStatus AddPackageFromPath (LPCWSTR lpswPath, PACKAGE_ADD_PROGRESS callbProgress) +{ + lastErrorCode = L""; + lastErrorDetailText = L""; + HANDLE completedEvent = nullptr; + try + { + completedEvent = CreateEventEx (nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS); + if (!completedEvent) return InstallStatus::Error; + String ^inputPackageUri = ref new String (lpswPath); + auto packageUri = ref new Uri (inputPackageUri); + auto packageManager = ref new PackageManager (); + auto deploymentOperation = packageManager->AddPackageAsync (packageUri, nullptr, DeploymentOptions::None); + deploymentOperation->Progress = + ref new AsyncOperationProgressHandler ( + [callbProgress] (IAsyncOperationWithProgress^ operation, DeploymentProgress progress) + { + if (callbProgress) + callbProgress (progress.percentage); + }); + deploymentOperation->Completed = + ref new AsyncOperationWithProgressCompletedHandler ( + [&completedEvent] (IAsyncOperationWithProgress^ operation, AsyncStatus) + { + SetEvent (completedEvent); + }); + WaitForSingleObject (completedEvent, INFINITE); + if (!completedEvent) + { + CloseHandle (completedEvent); completedEvent = nullptr; + } + if (deploymentOperation->Status == AsyncStatus::Error) + { + auto deploymentResult = deploymentOperation->GetResults (); + lastErrorCode += deploymentOperation->ErrorCode.Value; + lastErrorDetailText += deploymentResult->ErrorText->Data (); + return InstallStatus::Error; + } + else if (deploymentOperation->Status == AsyncStatus::Canceled) + { + lastErrorDetailText += L"Installation Canceled"; + return InstallStatus::Canceled; + } + else if (deploymentOperation->Status == AsyncStatus::Completed) + { + return InstallStatus::Success; + } + } + catch (Exception ^ex) + { + lastErrorDetailText += ex->ToString ()->Data (); + return InstallStatus::Error; + } + if (!completedEvent) + { + CloseHandle (completedEvent); completedEvent = nullptr; + } + return InstallStatus::Canceled; +} + +LPCWSTR GetLastErrorCode () +{ + if (lastErrorCode.length () == 0) return NULL; + else return lastErrorCode.c_str (); +} + +LPCWSTR GetLastErrorDetailText () +{ + if (lastErrorDetailText.length () == 0) return NULL; + else return lastErrorDetailText.c_str (); +} + +size_t GetLastErrorCodeLength () { return lastErrorCode.length (); } + +size_t GetLastErrorDetailTextLength () { return lastErrorDetailText.length (); } \ No newline at end of file diff --git a/PackageManagerAdd/stdafx.h b/PackageManagerAdd/stdafx.h new file mode 100644 index 0000000..474caa9 --- /dev/null +++ b/PackageManagerAdd/stdafx.h @@ -0,0 +1,12 @@ +#pragma once +#include +#include +#include +#include + +#using + +using namespace Platform; +using namespace Windows::Foundation; +using namespace Windows::Management::Deployment; +using namespace std; \ No newline at end of file diff --git a/PriReader/AddPackageSample.cpp b/PriReader/AddPackageSample.cpp new file mode 100644 index 0000000..0019257 --- /dev/null +++ b/PriReader/AddPackageSample.cpp @@ -0,0 +1,34 @@ +//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +//// PARTICULAR PURPOSE. +//// +//// Copyright (c) Microsoft Corporation. All rights reserved + +#include "stdafx.h" +#include "PackageManager.h" +#include +using namespace std; +void callback (unsigned progress) +{ + std::cout << '\r' << progress << "%" << std::ends; +} + +[MTAThread] +int __cdecl main(Platform::Array^ args) +{ + wcout << L"Copyright (c) Microsoft Corporation. All rights reserved." << endl; + wcout << L"Add Package" << endl << endl; + + if (args->Length < 2) + { + wcout << L"Usage: addpkg.exe packageUri" << endl; + return 1; + } + HANDLE completedEvent = nullptr; + int returnValue = 0; + String^ inputPackageUri = args[1]; + cout << endl; + AddPackageFromPath (inputPackageUri->Data (), &callback); + return 0; +} diff --git a/PriReader/AddPackageSample.vcxproj b/PriReader/AddPackageSample.vcxproj new file mode 100644 index 0000000..806307b --- /dev/null +++ b/PriReader/AddPackageSample.vcxproj @@ -0,0 +1,103 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + $(VCTargetsPath11) + 12.0 + + + Win32Proj + {59131AB7-2A7D-9A09-8223-174C3F5E0F57} + PriReader + + + + DynamicLibrary + true + v120 + Unicode + + + DynamicLibrary + false + v120 + Unicode + + + + + + + + + + + + + false + $(VCINSTALLDIR)\vcpackages;$(VCInstallDir)atlmfc\lib;$(VCInstallDir)lib;$(WindowsSdkDir)\References\CommonConfiguration\Neutral + + + false + $(VCINSTALLDIR)\vcpackages;$(VCInstallDir)atlmfc\lib;$(VCInstallDir)lib;$(WindowsSdkDir)\References\CommonConfiguration\Neutral + + + + WIN32;_DEBUG;PRIREADER_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + Level3 + ProgramDatabase + Disabled + true + false + /ZW:nostdlib /FUplatform.winmd /FUwindows.winmd %(AdditionalOptions) + Create + + + MachineX86 + true + NotSet + shlwapi.lib;runtimeobject.lib;%(AdditionalDependencies) + + + + + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + Level3 + ProgramDatabase + true + /ZW:nostdlib /FUplatform.winmd /FUWindows.winmd %(AdditionalOptions) + + + MachineX86 + true + Console + true + true + shlwapi.lib;runtimeobject.lib;%(AdditionalDependencies) + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/PriReader/PriReader.cpp b/PriReader/PriReader.cpp new file mode 100644 index 0000000..8be9ff9 --- /dev/null +++ b/PriReader/PriReader.cpp @@ -0,0 +1,84 @@ +#include "stdafx.h" +#include "PriReader.h" + +static HRESULT InitializeResourceManager (ComPtr& resourceManager) +{ + ComPtr resourceManagerStatics; + HRESULT hr = RoInitialize (RO_INIT_MULTITHREADED); + if (FAILED (hr)) + { + return hr; + } + hr = RoGetActivationFactory (HStringReference (RuntimeClass_Windows_ApplicationModel_Resources_Core_ResourceManager).Get (), IID_PPV_ARGS (&resourceManagerStatics)); + if (FAILED (hr)) + { + return hr; + } + // Windows 8 ʹ `GetCurrent` ȡȫ ResourceManager + hr = resourceManagerStatics->GetCurrent (&resourceManager); + return hr; +} + +static LPWSTR GetResourceValue (ComPtr resourceManager, LPCWSTR srcName) +{ + ComPtr resourceMap; + HRESULT hr = resourceManager->get_MainResourceMap (&resourceMap); + if (FAILED (hr)) + { + return nullptr; + } + + HSTRING hResourceName; + hr = WindowsCreateString (srcName, static_cast(wcslen (srcName)), &hResourceName); + if (FAILED (hr)) + { + return nullptr; + } + + ComPtr resourceCandidate; + hr = resourceMap->GetValue (hResourceName, &resourceCandidate); + WindowsDeleteString (hResourceName); + if (FAILED (hr)) + { + return nullptr; + } + HSTRING hResourceValue; + hr = resourceCandidate->get_ValueAsString (&hResourceValue); + if (FAILED (hr)) + { + return nullptr; + } + const wchar_t* resourceValue = WindowsGetStringRawBuffer (hResourceValue, nullptr); + LPWSTR result = (LPWSTR)calloc (wcslen (resourceValue) + 1, sizeof (wchar_t)); + if (result) + { + wcscpy_s (result, wcslen (resourceValue) + 1, resourceValue); + } + + WindowsDeleteString (hResourceValue); + return result; +} + +EXTERN_C LPWSTR GetStringValueFromPriSource (IStream* priFileStream, LPCWSTR srcName) +{ + // Windows 8 ֱ֧Ӽ PRI ļʡ stream + ComPtr resourceManager; + HRESULT hr = InitializeResourceManager (resourceManager); + if (FAILED (hr)) + { + return nullptr; + } + return GetResourceValue (resourceManager, srcName); +} + +EXTERN_C LPWSTR GetResourceValueFromPriSource (IStream* priFileStream, LPCWSTR srcName) +{ + // Windows 8 ֧Ĭ ResourceManager + ComPtr resourceManager; + HRESULT hr = InitializeResourceManager (resourceManager); + if (FAILED (hr)) + { + return nullptr; + } + return GetResourceValue (resourceManager, srcName); +} \ No newline at end of file diff --git a/PriReader/PriReader.h b/PriReader/PriReader.h new file mode 100644 index 0000000..3e55864 --- /dev/null +++ b/PriReader/PriReader.h @@ -0,0 +1,11 @@ +#pragma once +#ifdef PRIREADER_EXPORTS +#define PRIREADER_API __declspec(dllexport) +#else +#define PRIREADER_API __declspec(dllimport) +#endif + +#include + +EXTERN_C LPWSTR GetStringValueFromPriSource (IStream *priFileStream, LPCWSTR srcName); +EXTERN_C LPWSTR GetResourceValueFromPriSource (IStream *priFileStream, LPCWSTR srcName); \ No newline at end of file diff --git a/PriReader/PriReader.sln b/PriReader/PriReader.sln new file mode 100644 index 0000000..5afbb33 --- /dev/null +++ b/PriReader/PriReader.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 12 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AddPackageSample", "AddPackageSample.vcxproj", "{59131AB7-2A7D-9A09-8223-174C3F5E0F57}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {59131AB7-2A7D-9A09-8223-174C3F5E0F57}.Debug|Win32.ActiveCfg = Debug|Win32 + {59131AB7-2A7D-9A09-8223-174C3F5E0F57}.Debug|Win32.Build.0 = Debug|Win32 + {59131AB7-2A7D-9A09-8223-174C3F5E0F57}.Release|Win32.ActiveCfg = Release|Win32 + {59131AB7-2A7D-9A09-8223-174C3F5E0F57}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/PriReader/README.txt b/PriReader/README.txt new file mode 100644 index 0000000..09ff1df --- /dev/null +++ b/PriReader/README.txt @@ -0,0 +1,39 @@ +Add Package Sample +==================== +This sample demonstrates how to use IPackageManager to install a package. + +Prerequisites +============= +This sample requires Windows 8.1+. +This sample requires Visual Studio 12 Ultimate Developer Preview. +This sample requires the Windows Runtime Software Development Kit. + +Sample Language Implementations +=============================== +C++ + +Files: +====== +AddPackageSample.cpp + +To build the sample using the command prompt: +============================================= + 1. Open the Command Prompt window and navigate to the directory. + 2. Type msbuild AddPackageSample.sln. + + +To build the sample using Visual Studio 12 Ultimate Developer Preview (preferred method): +================================================ + 1. Open File Explorer and navigate to the directory. + 2. Double-click the icon for the .sln (solution) file to open the file in + Visual Studio. + 3. In the Build menu, select Build Solution. The application will be + built in the default \Debug or \Release directory. + + +To Run the sample: +================== + 1. Open a command prompt. + 2. Navigate to the directory containing AddPackageSample.exe + 2. Type AddPackageSample.exe "" at the command line. + For example, AddPackageSample.exe "file://C|/users/testuser/desktop/testpackage.appx" diff --git a/PriReader/stdafx.h b/PriReader/stdafx.h new file mode 100644 index 0000000..ce54ca0 --- /dev/null +++ b/PriReader/stdafx.h @@ -0,0 +1,18 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; +using namespace Windows::ApplicationModel::Resources::Core; + diff --git a/PriReader2/PriReader2.cpp b/PriReader2/PriReader2.cpp new file mode 100644 index 0000000..1c036f3 --- /dev/null +++ b/PriReader2/PriReader2.cpp @@ -0,0 +1,1879 @@ +// PriReader2.cpp : DLL Ӧóĵ +// + +#include "stdafx.h" +#include "localeex.h" +#include "PriReader2.h" + +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; +} +std::string GetProgramRootDirectoryA () +{ + char path [MAX_PATH]; + if (GetModuleFileNameA (NULL, path, MAX_PATH)) + { + std::string dir (path); + size_t pos = dir.find_last_of ("\\/"); + if (pos != std::string::npos) + { + dir = dir.substr (0, pos); + } + return dir; + } + return ""; +} +std::wstring GetProgramRootDirectoryW () +{ + wchar_t path [MAX_PATH]; + if (GetModuleFileNameW (NULL, path, MAX_PATH)) + { + std::wstring dir (path); + size_t pos = dir.find_last_of (L"\\/"); + if (pos != std::wstring::npos) + { + dir = dir.substr (0, pos); + } + return dir; + } + return L""; +} +std::string EnsureTrailingSlash (const std::string &path) +{ + if (path.empty ()) return path; // ·ֱӷ + + char lastChar = path.back (); + if (lastChar == '\\' || lastChar == '/') + return path; // зֱָӷ + // ϵͳԭ·ʽʵķָ + char separator = (path.find ('/') != std::string::npos) ? '/' : '\\'; + return path + separator; +} +std::wstring EnsureTrailingSlash (const std::wstring &path) +{ + if (path.empty ()) return path; + + wchar_t lastChar = path.back (); + if (lastChar == L'\\' || lastChar == L'/') + return path; + + wchar_t separator = (path.find (L'/') != std::wstring::npos) ? L'/' : L'\\'; + return path + separator; +} +extern "C" bool IsFileExistsW (LPCWSTR filename) +{ + DWORD dwAttrib = GetFileAttributesW (filename); + return (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)); +} +extern "C" 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 ()); } +bool IsDirectoryExistsA (LPCSTR path) +{ + DWORD attributes = GetFileAttributesA (path); + return (attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_DIRECTORY)); +} +bool IsDirectoryExistsW (LPCWSTR path) +{ + DWORD attributes = GetFileAttributesW (path); + return (attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_DIRECTORY)); +} +bool IsDirectoryExists (const std::string path) { return IsDirectoryExistsA (path.c_str ()); } +bool IsDirectoryExists (const std::wstring path) { return IsDirectoryExistsW (path.c_str ()); } +bool IsDirectoryExists (LPCSTR path) { return IsDirectoryExistsA (path); } +bool IsDirectoryExists (LPCWSTR path) { return IsDirectoryExistsW (path); } +std::string NormalizePath (const std::string &path) +{ + if (!path.empty () && path.back () == '\\') + return path.substr (0, path.size () - 1); + return path; +} +std::wstring NormalizePath (const std::wstring &path) +{ + if (!path.empty () && path.back () == L'\\') + return path.substr (0, path.size () - 1); + return path; +} +std::vector EnumSubdirectories (const std::string &directory, bool includeParentPath) +{ + std::vector subdirs; + std::string normPath = NormalizePath (directory); + std::string searchPath = normPath + "\\*"; + WIN32_FIND_DATAA findData; + HANDLE hFind = FindFirstFileA (searchPath.c_str (), &findData); + if (hFind == INVALID_HANDLE_VALUE) return subdirs; + do + { + // "." ".." + if (strcmp (findData.cFileName, ".") == 0 || strcmp (findData.cFileName, "..") == 0) + continue; + // жǷΪĿ¼ + if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + if (includeParentPath) + subdirs.push_back (normPath + "\\" + findData.cFileName); + else + subdirs.push_back (findData.cFileName); + } + } while (FindNextFileA (hFind, &findData)); + FindClose (hFind); + return subdirs; +} +std::vector EnumSubdirectories (const std::wstring &directory, bool includeParentPath) +{ + std::vector subdirs; + std::wstring normPath = NormalizePath (directory); + std::wstring searchPath = normPath + L"\\*"; + WIN32_FIND_DATAW findData; + HANDLE hFind = FindFirstFileW (searchPath.c_str (), &findData); + if (hFind == INVALID_HANDLE_VALUE) return subdirs; + do + { + if (wcscmp (findData.cFileName, L".") == 0 || wcscmp (findData.cFileName, L"..") == 0) + continue; + if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + if (includeParentPath) + subdirs.push_back (normPath + L"\\" + findData.cFileName); + else + subdirs.push_back (findData.cFileName); + } + } while (FindNextFileW (hFind, &findData)); + FindClose (hFind); + return subdirs; +} +bool CheckDependency (const std::string &dllName) +{ + HMODULE hModule = LoadLibraryA (dllName.c_str ()); + if (hModule == NULL) + { + return false; + } + FreeLibrary (hModule); + return true; +} +bool CheckDependency (const std::wstring &dllName) +{ + HMODULE hModule = LoadLibraryW (dllName.c_str ()); + if (hModule == NULL) + { + return false; + } + FreeLibrary (hModule); + return true; +} +bool CanRunExe (const std::string &exePath) +{ + STARTUPINFOA si = {sizeof (si)}; + PROCESS_INFORMATION pi; + BOOL success = CreateProcessA ( + exePath.c_str (), // Ӧ· + NULL, // в + NULL, // ȫ + NULL, // ̰߳ȫ + FALSE, // ̳о + CREATE_NO_WINDOW, // + NULL, // + NULL, // ǰĿ¼ + &si, // Ϣ + &pi // Ϣ + ); + if (!success) + { + DWORD error = GetLastError (); + return false; + } + WaitForSingleObject (pi.hProcess, INFINITE); + DWORD exitCode; + GetExitCodeProcess (pi.hProcess, &exitCode); + CloseHandle (pi.hProcess); + CloseHandle (pi.hThread); + return (exitCode == 0); +} +bool CanRunExe (const std::wstring& exePath) +{ + STARTUPINFOW si = {sizeof (si)}; + PROCESS_INFORMATION pi; + BOOL success = CreateProcessW ( + exePath.c_str (), // Ӧ· + NULL, // в + NULL, // ȫ + NULL, // ̰߳ȫ + FALSE, // ̳о + CREATE_NO_WINDOW, // + NULL, // + NULL, // ǰĿ¼ + &si, // Ϣ + &pi // Ϣ + ); + if (!success) + { + DWORD error = GetLastError (); + return false; + } + WaitForSingleObject (pi.hProcess, INFINITE); + DWORD exitCode; + GetExitCodeProcess (pi.hProcess, &exitCode); + CloseHandle (pi.hProcess); + CloseHandle (pi.hThread); + return (exitCode == 0); +} +bool IsProgramExecutable (const std::string &exePath) +{ + if (!IsFileExists (exePath)) + { + return false; + } + if (!CanRunExe (exePath)) + { + return false; + } + return true; +} +bool IsProgramExecutable (const std::wstring &exePath) +{ + if (!IsFileExists (exePath)) + { + return false; + } + if (!CanRunExe (exePath)) + { + return false; + } + return true; +} +std::wstring GetUniqueTempFilePathW () +{ + // ȡʱļ· + wchar_t tempPath [MAX_PATH]; + if (GetTempPath (MAX_PATH, tempPath) == 0) + { + return L""; + } + // һΨһʱļ + wchar_t tempFile [MAX_PATH]; + if (GetTempFileName (tempPath, L"TMP", 0, tempFile) == 0) + { + return L""; + } + return tempFile; +} +std::string GetUniqueTempFilePathA () { + // ȡʱļ· + char tempPath [MAX_PATH]; + if (GetTempPathA (MAX_PATH, tempPath) == 0) + { + return ""; + } + // һΨһʱļ + char tempFile [MAX_PATH]; + if (GetTempFileNameA (tempPath, "TMP", 0, tempFile) == 0) + { + return ""; + } + return tempFile; +} +std::wstring StringTrim (const std::wstring &str) +{ + if (str.empty ()) return L""; + LPCWSTR start = str.c_str (); + LPCWSTR end = start + str.size () - 1; +#define isblankstrlabelw(wch) (wch == L' ' || wch == L'\t' || wch == L'\n') + while (*start != L'\0' && isblankstrlabelw (*start)) ++start; + while (end >= start && isblankstrlabelw (*end)) --end; + if (start > end) return L""; + return std::wstring (start, end + 1); +} +std::string StringTrim (const std::string &str) +{ + if (str.empty ()) return ""; + LPCSTR start = str.c_str (); + LPCSTR end = start + str.size () - 1; +#define isblankstrlabela(wch) (wch == ' ' || wch == '\t' || wch == '\n') + while (*start != L'\0' && isblankstrlabela (*start)) ++start; + while (end >= start && isblankstrlabela (*end)) --end; + if (start > end) return ""; + return std::string (start, end + 1); +} +namespace l0km +{ + template < typename E, + typename TR = std::char_traits, + typename AL = std::allocator < E >> + 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 E, + typename TR = std::char_traits, + typename AL = std::allocator < E >> + 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; + } +} // namespace l0km +#define StringToUpper l0km::toupper +#define StringToLower l0km::tolower +int LabelCompare (const std::wstring &l1, const std::wstring &l2) +{ + std::wstring s1 = StringToUpper (StringTrim (l1)), + s2 = StringToUpper (StringTrim (l2)); + return lstrcmpW (s1.c_str (), s2.c_str ()); +} +int LabelCompare (LPCWSTR l1, LPCWSTR l2) +{ + return LabelCompare (std::wstring (l1), std::wstring (l2)); +} +int LabelCompare (const std::string &l1, const std::string &l2) +{ + std::string s1 = StringToUpper (StringTrim (l1)), + s2 = StringToUpper (StringTrim (l2)); + return lstrcmpA (s1.c_str (), s2.c_str ()); +} +int LabelCompare (LPCSTR l1, LPCSTR l2) +{ + return LabelCompare (std::string (l1), std::string (l2)); +} +bool LabelEqual (const std::wstring &l1, const std::wstring &l2) +{ + return !LabelCompare (l1, l2); +} +bool LabelEqual (LPCWSTR l1, LPCWSTR l2) +{ + return !LabelCompare (l1, l2); +} +bool LabelEqual (const std::string &l1, const std::string &l2) +{ + return !LabelCompare (l1, l2); +} +bool LabelEqual (LPCSTR l1, LPCSTR l2) +{ + return !LabelCompare (l1, l2); +} +int InStr (const std::string &text, const std::string &keyword, bool ignoreCase = false) +{ + std::string s1, s2; + if (ignoreCase) + { + s1 = StringToUpper (text); + s2 = StringToUpper (keyword); + } + else + { + s1 = text; + s2 = keyword; + } + const char *found = StrStrIA (s1.c_str (), s2.c_str ()); + if (!found) + { + return -1; + } + return found - text.c_str (); +} +int InStr (const std::wstring &text, const std::wstring &keyword, bool ignoreCase = false) +{ + std::wstring s1, s2; + if (ignoreCase) + { + s1 = StringToUpper (text); + s2 = StringToUpper (keyword); + } + else + { + s1 = text; + s2 = keyword; + } + const WCHAR *found = StrStrIW (s1.c_str (), s2.c_str ()); + if (!found) + { + return -1; + } + return found - text.c_str (); +} + +enum class ProcessorArchitecture +{ + x86 = 1, + x64 = 2, + arm = 3, + arm64 = 4 +}; + +typedef struct VERSION +{ + UINT16 build, maintenance, minor, major; + VERSION (UINT16 major, UINT16 minor, UINT16 maintenance, UINT16 build); + VERSION (UINT64 ver); + VERSION (); + virtual ~VERSION (); + std::wstring toStringW (); + std::string toString (); + bool isEmpty (); + UINT64 getUInt64 (); + INT64 compare (VERSION &another); + bool equals (VERSION &another); + bool operator == (VERSION &another) { return this->equals (another); } + bool operator > (VERSION &another) { return this->getUInt64 () > another.getUInt64 (); } + bool operator < (VERSION &another) { return this->getUInt64 () < another.getUInt64 (); } + bool operator >= (VERSION &another) { return !(*this < another); } + bool operator <= (VERSION &another) { return !(*this > another); } + bool operator != (VERSION &another) { return !this->equals (another); } + static VERSION stringTo (const std::string &str); + static VERSION stringTo (const std::wstring &str); + static VERSION stringTo (LPCSTR str); + static VERSION stringTo (LPCWSTR str); + VERSION setFromString (const std::string &str) + { + VERSION v = stringTo (str); + this->major = v.major; + this->minor = v.minor; + this->maintenance = v.maintenance; + this->build = v.build; + return *this; + } + VERSION setFromString (const std::wstring &str) + { + VERSION v = stringTo (str); + this->major = v.major; + this->minor = v.minor; + this->maintenance = v.maintenance; + this->build = v.build; + return *this; + } + private: + static std::vector splitVersionString (const std::string &str); + static std::vector splitVersionString (const std::wstring &str); +} _VERSION, VERSION, Version, version; +VERSION::VERSION (UINT16 major, UINT16 minor, UINT16 maintenance, UINT16 build): + major (major), minor (minor), maintenance (maintenance), build (build) {} +VERSION::VERSION (UINT64 verdata) : major ((verdata >> 0x30) & 0xFFFF), minor ((verdata >> 0x20) & 0xFFFF), +maintenance ((verdata >> 0x10) & 0xFFFF), build ((verdata) & 0xFFFF) {} +VERSION::VERSION () : major (0), minor (0), maintenance (0), build (0) {} +VERSION::~VERSION () +{ + this->major = 0; + this->minor = 0; + this->maintenance = 0; + this->build = 0; +} +std::wstring VERSION::toStringW () +{ + std::wstringstream ss; + ss << this->major << L'.' << this->minor << L'.' << this->maintenance << L'.' << this->build << std::ends; + std::wstring st (L""); + st += ss.str (); + return st; +} +std::string VERSION::toString () +{ + std::stringstream ss; + ss << this->major << '.' << this->minor << '.' << this->maintenance << '.' << this->build << std::ends; + std::string st (""); + st += ss.str (); + return st; +} +bool VERSION::isEmpty () +{ + return this->getUInt64 () == 0; +} +UINT64 VERSION::getUInt64 () +{ + UINT64 u64 = (((UINT64)major) << 0x30) | (((UINT64)minor) << 0x20) | (((UINT64)maintenance) << 0x10) | ((UINT64)build); + return u64; +} +INT64 VERSION::compare (VERSION &another) +{ + UINT64 u1 = this->getUInt64 (), u2 = another.getUInt64 (); + return u1 - u2; +} +bool VERSION::equals (VERSION &another) +{ + return !this->compare (another); +} +std::vector VERSION::splitVersionString (const std::string &str) +{ + std::vector result; + std::stringstream ss (str); + std::string segment; + while (std::getline (ss, segment, '.')) // Ȱ '.' + { + size_t pos = 0; + while ((pos = segment.find (',')) != std::string::npos) // ٰ ',' + { + result.push_back (segment.substr (0, pos)); + segment.erase (0, pos + 1); + } + result.push_back (segment); + } + return result; +} +std::vector VERSION::splitVersionString (const std::wstring &str) +{ + std::vector result; + std::wstringstream ss (str); + std::wstring segment; + while (std::getline (ss, segment, L'.')) // Ȱ '.' + { + size_t pos = 0; + while ((pos = segment.find (L',')) != std::wstring::npos) // ٰ ',' + { + result.push_back (segment.substr (0, pos)); + segment.erase (0, pos + 1); + } + result.push_back (segment); + } + return result; +} +VERSION VERSION::stringTo (const std::string &str) +{ + std::vector parts = splitVersionString (str); + UINT16 major = (parts.size () > 0) ? static_cast(std::stoi (parts [0])) : 0; + UINT16 minor = (parts.size () > 1) ? static_cast(std::stoi (parts [1])) : 0; + UINT16 maintenance = (parts.size () > 2) ? static_cast(std::stoi (parts [2])) : 0; + UINT16 build = (parts.size () > 3) ? static_cast(std::stoi (parts [3])) : 0; + return VERSION (major, minor, maintenance, build); +} +VERSION VERSION::stringTo (const std::wstring &str) +{ + std::vector parts = splitVersionString (str); + UINT16 major = (parts.size () > 0) ? static_cast(std::stoi (parts [0])) : 0; + UINT16 minor = (parts.size () > 1) ? static_cast(std::stoi (parts [1])) : 0; + UINT16 maintenance = (parts.size () > 2) ? static_cast(std::stoi (parts [2])) : 0; + UINT16 build = (parts.size () > 3) ? static_cast(std::stoi (parts [3])) : 0; + return VERSION (major, minor, maintenance, build); +} +VERSION VERSION::stringTo (LPCSTR str) +{ + return stringTo (std::string (str)); +} +VERSION VERSION::stringTo (LPCWSTR str) +{ + return stringTo (std::wstring (str)); +} + +struct ProgramExeInfo +{ + std::wstring filePath; + ProcessorArchitecture process; + VERSION version; + ProgramExeInfo (std::wstring filePath, ProcessorArchitecture process, VERSION version): filePath (filePath), process (process), version (version) {} + ProgramExeInfo (): filePath (L""), process (ProcessorArchitecture::x86), version (0) {} + bool operator == (ProgramExeInfo &another) + { + return LabelEqual (this->filePath, another.filePath) && this->process == another.process && this->version == another.version; + } + bool operator < (ProgramExeInfo &another) + { + if (this->version > another.version) return true; + if (this->version < another.version) return false; + return static_cast(this->process) < static_cast(another.process); + } +}; + +ProcessorArchitecture GetProcessorArchitecture () +{ + SYSTEM_INFO sysInfo; + GetSystemInfo (&sysInfo); + switch (sysInfo.wProcessorArchitecture) + { + case PROCESSOR_ARCHITECTURE_INTEL: + return ProcessorArchitecture::x86; // 32-bit Intel + case PROCESSOR_ARCHITECTURE_AMD64: + return ProcessorArchitecture::x64; // 64-bit Intel/AMD + case PROCESSOR_ARCHITECTURE_ARM: + return ProcessorArchitecture::arm; // ARM + case 12: + return ProcessorArchitecture::arm64; // ARM64 + default: + throw std::runtime_error ("Unknown processor architecture."); + } + return ProcessorArchitecture::x86; +} + +template StringType ReplaceBackslash (const StringType &input) +{ + StringType result = input; // ַ޸ԭ + using CharType = typename StringType::value_type; // ȡַַͣchar wchar_t + std::replace (result.begin (), result.end (), static_cast ('\\'), static_cast ('/')); + return result; +} + +HRESULT ExtractFileFromStream (_In_ IStream* ifile, _In_ LPCWSTR outputFilePath) +{ + if (ifile == nullptr || outputFilePath == nullptr) + { + return E_INVALIDARG; + } + HRESULT hr = S_OK; + IStream* outputStream = nullptr; + ULARGE_INTEGER fileSizeLargeInteger = {0}; + STATSTG statstg = {0}; + // ȡĴС + hr = ifile->Stat (&statstg, STATFLAG_NONAME); + if (SUCCEEDED (hr)) + { + fileSizeLargeInteger.QuadPart = statstg.cbSize.QuadPart; + } + // ļ IStream + if (SUCCEEDED (hr)) + { + hr = SHCreateStreamOnFileEx ( + outputFilePath, + STGM_CREATE | STGM_READWRITE | STGM_SHARE_DENY_NONE, + 0, + TRUE, + NULL, + &outputStream); + } + // ݵ + if (SUCCEEDED (hr)) + { + hr = ifile->CopyTo (outputStream, fileSizeLargeInteger, nullptr, nullptr); + } + // ȷȫд + if (SUCCEEDED (hr) && outputStream) + { + hr = outputStream->Commit (STGC_DEFAULT); // ˢ» + } + // ͷԴ + if (outputStream) + { + outputStream->Release (); + } + return hr; +} + +class PriReader +{ + private: + static std::wstring makepri; + std::wstring prifile = L""; + std::wstring txmlpath = L""; + pugi::xml_document *xmlreader; + static bool initMakePri () + { + if (IsFileExists (makepri)) return true; // ظʼ + std::wstring rootpath = EnsureTrailingSlash (EnsureTrailingSlash (GetProgramRootDirectoryW ()) + L"Tools\\MakePRI"); + if (!IsDirectoryExists (rootpath)) rootpath = L"Tools\\MakePRI"; + if (!IsDirectoryExists (rootpath)) return false; + std::vector vers = EnumSubdirectories (rootpath, false); + if (!vers.size ()) return false; + std::vector einf; + for (auto it : vers) + { + // x86 + { + ProgramExeInfo pe; + pe.filePath = EnsureTrailingSlash (EnsureTrailingSlash (rootpath) + it) + L"x86\\makepri.exe"; + pe.process = ProcessorArchitecture::x86; + pe.version = VERSION::stringTo (it); + if (IsFileExists (pe.filePath)) + { + if (!pe.version.isEmpty ()) + { + einf.push_back (pe); + } + } + } + // x64 + { + ProgramExeInfo pe; + pe.filePath = EnsureTrailingSlash (EnsureTrailingSlash (rootpath) + it) + L"x64\\makepri.exe"; + pe.process = ProcessorArchitecture::x64; + pe.version = VERSION::stringTo (it); + if (IsFileExists (pe.filePath)) + { + if (!pe.version.isEmpty ()) + { + einf.push_back (pe); + } + } + } + // arm + { + ProgramExeInfo pe; + pe.filePath = EnsureTrailingSlash (EnsureTrailingSlash (rootpath) + it) + L"arm\\makepri.exe"; + pe.process = ProcessorArchitecture::arm; + pe.version = VERSION::stringTo (it); + if (IsFileExists (pe.filePath)) + { + if (!pe.version.isEmpty ()) + { + einf.push_back (pe); + } + } + } + // arm64 + { + ProgramExeInfo pe; + pe.filePath = EnsureTrailingSlash (EnsureTrailingSlash (rootpath) + it) + L"arm64\\makepri.exe"; + pe.process = ProcessorArchitecture::arm64; + pe.version = VERSION::stringTo (it); + if (IsFileExists (pe.filePath)) + { + if (!pe.version.isEmpty ()) + { + einf.push_back (pe); + } + } + } + } + size_t n = einf.size (); + for (size_t i = 0; i < n - 1; i ++) + { + for (size_t j = 0; j < n - 1 - i; j ++) + { + if (einf [j].version < einf [j + 1].version) + { + std::swap (einf [j], einf [j + 1]); + } + } + } + ProcessorArchitecture syspa = GetProcessorArchitecture (); + for (auto it : einf) + { + switch (syspa) + { + case ProcessorArchitecture::x64: + if (it.process == ProcessorArchitecture::x64) + { + if (IsProgramExecutable (it.filePath)) + { + PriReader::makepri = it.filePath; + return true; + } + } + case ProcessorArchitecture::x86: + if (it.process == ProcessorArchitecture::x86) + { + if (IsProgramExecutable (it.filePath)) + { + PriReader::makepri = it.filePath; + return true; + } + } break; + case ProcessorArchitecture::arm64: + if (it.process == ProcessorArchitecture::arm64) + { + if (IsProgramExecutable (it.filePath)) + { + PriReader::makepri = it.filePath; + return true; + } + } + case ProcessorArchitecture::arm: + if (it.process == ProcessorArchitecture::arm) + { + if (IsProgramExecutable (it.filePath)) + { + PriReader::makepri = it.filePath; + return true; + } + } break; + } + } + return false; + } + bool isLanguageMatch (const std::string l1, const std::string l2) + { + bool isLanguageMatch = LabelEqual (l1, l2); + if (!isLanguageMatch) + { + bool isLanguageMatch = ( + LocaleCodeToLcidA (l1.c_str ()) + == + LocaleCodeToLcidA (l2.c_str ()) + ); + } + if (!isLanguageMatch) + { + bool isLanguageMatch = LabelEqual ( + GetLocaleRestrictedCodeA (l1), + GetLocaleRestrictedCodeA (l2) + ); + } + return isLanguageMatch; + } + bool isLanguageMatch (LPCSTR l1, LPCSTR l2) + { + return isLanguageMatch (std::string (l1), std::string (l2)); + } + bool isLanguageMatch (const std::wstring l1, const std::wstring l2) + { + bool isLanguageMatch = LabelEqual (l1, l2); + if (!isLanguageMatch) + { + bool isLanguageMatch = ( + LocaleCodeToLcidW (l1.c_str ()) + == + LocaleCodeToLcidW (l2.c_str ()) + ); + } + if (!isLanguageMatch) + { + bool isLanguageMatch = LabelEqual ( + GetLocaleRestrictedCodeW (l1), + GetLocaleRestrictedCodeW (l2) + ); + } + return isLanguageMatch; + } + bool isLanguageMatch (LPCWSTR l1, LPCWSTR l2) + { + return isLanguageMatch (std::wstring (l1), std::wstring (l2)); + } + LPSTR recFindStringValue (pugi::xml_node &subResMap, LPCSTR lpMsName, LPCSTR defaultLocaleCode) + { + for (pugi::xml_node namedRes = subResMap.child ("NamedResource"); namedRes; namedRes = namedRes.next_sibling ("NamedResource")) + { + bool isMatch = false; + pugi::xml_attribute nameAttr = namedRes.attribute ("name"); + std::string resname = nameAttr.as_string (); + isMatch = LabelEqual (resname, lpMsName); + static const std::regex pattern ("^ms-resource:", std::regex_constants::icase); + if (!isMatch) + { + std::string lpname2 = std::regex_replace (std::string (lpMsName), pattern, ""); + isMatch = LabelEqual (resname, lpname2); + } + if (!isMatch) + { + pugi::xml_attribute uriAttr = namedRes.attribute ("uri"); + std::string resuri = uriAttr.as_string (); + isMatch = (InStr (resuri, resname) >= 0); + } + if (isMatch) + { + std::map langmap; + for (pugi::xml_node candidate = namedRes.child ("Candidate"); candidate; candidate = candidate.next_sibling ("Candidate")) + { + pugi::xml_attribute typeAttr = candidate.attribute ("type"); + if (!LabelEqual (typeAttr.as_string (), "String")) continue; + std::string valueGet = candidate.child ("Value").text ().get (); + for (pugi::xml_node qualifierSet = candidate.child ("QualifierSet"); qualifierSet; qualifierSet = qualifierSet.next_sibling ("QualifierSet")) + { + for (pugi::xml_node qualifier = qualifierSet.child ("Qualifier"); qualifier; qualifier = qualifier.next_sibling ("Qualifier")) + { + if (!LabelEqual (qualifier.attribute ("name").as_string (), "Language")) continue; + std::string value = qualifier.attribute ("value").as_string (); + langmap [std::string (value)] = valueGet; + } + } + } + for (auto it : langmap) + { + bool isMatch = LabelEqual (it.first, defaultLocaleCode); + if (!isMatch) isMatch = ( + LocaleCodeToLcidA (it.first.c_str ()) + == + LocaleCodeToLcidA (defaultLocaleCode) + ); + if (isMatch) + { + LPSTR lpbuf = (LPSTR)malloc (it.second.capacity () * sizeof (char)); + ZeroMemory (lpbuf, it.second.capacity ()); + lstrcpyA (lpbuf, it.second.c_str ()); + return lpbuf; + } + } + for (auto it : langmap) + { + bool isMatch = isLanguageMatch (it.first, defaultLocaleCode); + if (isMatch) + { + LPSTR lpbuf = (LPSTR)malloc (it.second.capacity () * sizeof (char)); + ZeroMemory (lpbuf, it.second.capacity ()); + lstrcpyA (lpbuf, it.second.c_str ()); + return lpbuf; + } + } + for (auto it : langmap) + { + bool isMatch = LabelEqual (it.first, LcidToLocaleCodeA (GetSystemDefaultLCID ())); + if (!isMatch) isMatch = ( + LocaleCodeToLcidA (it.first.c_str ()) + == + LocaleCodeToLcidA (LcidToLocaleCodeA (GetSystemDefaultLCID ()).c_str ()) + ); + if (isMatch) + { + LPSTR lpbuf = (LPSTR)malloc (it.second.capacity () * sizeof (char)); + ZeroMemory (lpbuf, it.second.capacity ()); + lstrcpyA (lpbuf, it.second.c_str ()); + return lpbuf; + } + } + for (auto it : langmap) + { + bool isMatch = isLanguageMatch (it.first, LcidToLocaleCodeA (GetSystemDefaultLCID ())); + if (isMatch) + { + LPSTR lpbuf = (LPSTR)malloc (it.second.capacity () * sizeof (char)); + ZeroMemory (lpbuf, it.second.capacity ()); + lstrcpyA (lpbuf, it.second.c_str ()); + return lpbuf; + } + } + for (auto it : langmap) + { + bool isMatch = isLanguageMatch (it.first, "en-us"); + if (isMatch) + { + LPSTR lpbuf = (LPSTR)malloc (it.second.capacity () * sizeof (char)); + ZeroMemory (lpbuf, it.second.capacity ()); + lstrcpyA (lpbuf, it.second.c_str ()); + return lpbuf; + } + } + for (auto it : langmap) + { + bool isMatch = isLanguageMatch (it.first, "en"); + if (isMatch) + { + LPSTR lpbuf = (LPSTR)malloc (it.second.capacity () * sizeof (char)); + ZeroMemory (lpbuf, it.second.capacity ()); + lstrcpyA (lpbuf, it.second.c_str ()); + return lpbuf; + } + } + for (auto it : langmap) + { + LPSTR lpbuf = (LPSTR)malloc (it.second.capacity () * sizeof (char)); + ZeroMemory (lpbuf, it.second.capacity ()); + lstrcpyA (lpbuf, it.second.c_str ()); + return lpbuf; + } + } + } + for (pugi::xml_node subtree = subResMap.child ("ResourceMapSubtree"); subtree; subtree = subtree.next_sibling ("ResourceMapSubtree")) + { + LPSTR result = recFindStringValue (subtree, lpMsName, defaultLocaleCode); + if (result) return result; // ҵͷ + } + return NULL; + } + LPWSTR recFindStringValue (pugi::xml_node &subResMap, LPCWSTR lpMsName, LPCWSTR defaultLocaleCode) + { + for (pugi::xml_node namedRes = subResMap.child ("NamedResource"); namedRes; namedRes = namedRes.next_sibling ("NamedResource")) + { + bool isMatch = false; + pugi::xml_attribute nameAttr = namedRes.attribute ("name"); + std::wstring resname = pugi::as_wide (nameAttr.as_string ()); + isMatch = LabelEqual (resname, lpMsName); + static const std::wregex pattern (L"^ms-resource:", std::regex_constants::icase); + if (!isMatch) + { + std::wstring lpname2 = std::regex_replace (std::wstring (lpMsName), pattern, L""); + isMatch = LabelEqual (resname, lpname2); + } + if (!isMatch) + { + pugi::xml_attribute uriAttr = namedRes.attribute ("uri"); + std::wstring resuri = pugi::as_wide (uriAttr.as_string ()); + isMatch = (InStr (resuri, lpMsName, true) >= 0); + } + if (!isMatch) + { + std::wstring lpname2 = std::regex_replace (std::wstring (lpMsName), pattern, L""); + pugi::xml_attribute uriAttr = namedRes.attribute ("uri"); + std::wstring resuri = pugi::as_wide (uriAttr.as_string ()); + isMatch = (InStr (resuri, lpname2, true) >= 0); + } + if (isMatch) + { + std::map langmap; + for (pugi::xml_node candidate = namedRes.child ("Candidate"); candidate; candidate = candidate.next_sibling ("Candidate")) + { + pugi::xml_attribute typeAttr = candidate.attribute ("type"); + if (!LabelEqual (typeAttr.as_string (), "String")) continue; + for (pugi::xml_node qualifierSet = candidate.child ("QualifierSet"); qualifierSet; qualifierSet = qualifierSet.next_sibling ("QualifierSet")) + { + std::wstring valueGet = pugi::as_wide (candidate.child ("Value").text ().get ()); + for (pugi::xml_node qualifier = qualifierSet.child ("Qualifier"); qualifier; qualifier = qualifier.next_sibling ("Qualifier")) + { + if (!LabelEqual (qualifier.attribute ("name").as_string (), "Language")) continue; + std::wstring value = pugi::as_wide (qualifier.attribute ("value").as_string ()); + langmap [std::wstring (value)] = valueGet; + } + } + } + for (auto it : langmap) + { + bool isMatch = LabelEqual (it.first, defaultLocaleCode); + if (!isMatch) { + isMatch = (LocaleCodeToLcidW (it.first.c_str ()) == LocaleCodeToLcidW (defaultLocaleCode)); + } + if (isMatch) { + LPWSTR lpbuf = (LPWSTR)malloc ((it.second.length () + 1) * sizeof (wchar_t)); + ZeroMemory (lpbuf, (it.second.length () + 1) * sizeof (wchar_t)); + lstrcpyW (lpbuf, it.second.c_str ()); + return lpbuf; + } + } + for (auto it : langmap) + { + if (isLanguageMatch (it.first, defaultLocaleCode)) + { + LPWSTR lpbuf = (LPWSTR)malloc ((it.second.length () + 1) * sizeof (wchar_t)); + ZeroMemory (lpbuf, (it.second.length () + 1) * sizeof (wchar_t)); + lstrcpyW (lpbuf, it.second.c_str ()); + return lpbuf; + } + } + for (auto it : langmap) + { + bool isMatch = LabelEqual (it.first, LcidToLocaleCodeW (GetSystemDefaultLCID ())); + if (!isMatch) + { + isMatch = (LocaleCodeToLcidW (it.first.c_str ()) == LocaleCodeToLcidW (LcidToLocaleCodeW (GetSystemDefaultLCID ()).c_str ())); + } + if (isMatch) + { + LPWSTR lpbuf = (LPWSTR)malloc ((it.second.length () + 1) * sizeof (wchar_t)); + ZeroMemory (lpbuf, (it.second.length () + 1) * sizeof (wchar_t)); + lstrcpyW (lpbuf, it.second.c_str ()); + return lpbuf; + } + } + for (auto it : langmap) + { + if (isLanguageMatch (it.first, LcidToLocaleCodeW (GetSystemDefaultLCID ()))) + { + LPWSTR lpbuf = (LPWSTR)malloc ((it.second.length () + 1) * sizeof (wchar_t)); + ZeroMemory (lpbuf, (it.second.length () + 1) * sizeof (wchar_t)); + lstrcpyW (lpbuf, it.second.c_str ()); + return lpbuf; + } + } + for (auto it : langmap) + { + if (isLanguageMatch (it.first, L"en-us")) + { + LPWSTR lpbuf = (LPWSTR)malloc ((it.second.length () + 1) * sizeof (wchar_t)); + ZeroMemory (lpbuf, (it.second.length () + 1) * sizeof (wchar_t)); + lstrcpyW (lpbuf, it.second.c_str ()); + return lpbuf; + } + } + for (auto it : langmap) + { + if (isLanguageMatch (it.first, L"en")) + { + LPWSTR lpbuf = (LPWSTR)malloc ((it.second.length () + 1) * sizeof (wchar_t)); + ZeroMemory (lpbuf, (it.second.length () + 1) * sizeof (wchar_t)); + lstrcpyW (lpbuf, it.second.c_str ()); + return lpbuf; + } + } + for (auto it : langmap) + { + LPWSTR lpbuf = (LPWSTR)malloc ((it.second.length () + 1) * sizeof (wchar_t)); + ZeroMemory (lpbuf, (it.second.length () + 1) * sizeof (wchar_t)); + lstrcpyW (lpbuf, it.second.c_str ()); + return lpbuf; + } + } + } + // ݹ + for (pugi::xml_node subtree = subResMap.child ("ResourceMapSubtree"); subtree; subtree = subtree.next_sibling ("ResourceMapSubtree")) + { + LPWSTR result = recFindStringValue (subtree, lpMsName, defaultLocaleCode); + if (result) return result; + } + return NULL; + } + struct ImageFileInfo + { + int scale; + ImageContrast contrast; + size_t hash; + ImageFileInfo (int scale = 100, ImageContrast contrast = ImageContrast::none, size_t hash = 0): + scale (scale), contrast (contrast), hash (hash) {} + bool operator < (const ImageFileInfo &right) const + { + if (scale != right.scale) + return scale < right.scale; + if (contrast != right.contrast) + return contrast < right.contrast; + return hash < right.hash; // ȷֶζ + } + bool operator == (const ImageFileInfo &right) const + { + return this->scale == right.scale && this->contrast == right.contrast && this->hash == right.hash; + } + bool operator != (const ImageFileInfo &right) const { return !(*this == right); } + }; + LPSTR recFindFilePathValue (pugi::xml_node &subResMap, LPCSTR lpMsName, int defaultScale = GetDPI (), ImageContrast defaultContrast = ImageContrast::none) + { + for (pugi::xml_node namedRes = subResMap.child ("NamedResource"); namedRes; namedRes = namedRes.next_sibling ("NamedResource")) + { + bool isMatch = false; + pugi::xml_attribute nameAttr = namedRes.attribute ("name"); + std::string resname = nameAttr.as_string (); + isMatch = LabelEqual (resname, lpMsName); + static const std::regex pattern ("^ms-resource:", std::regex_constants::icase); + if (!isMatch) + { + std::string lpname2 = std::regex_replace (std::string (lpMsName), pattern, ""); + isMatch = LabelEqual (resname, lpname2); + } + if (!isMatch) + { + LPCSTR filename = PathFindFileNameA (lpMsName); + isMatch = LabelEqual (resname, filename); + } + if (!isMatch) + { + pugi::xml_attribute uriAttr = namedRes.attribute ("uri"); + std::string resuri = uriAttr.as_string (); + std::string ptouri = ReplaceBackslash (std::string (lpMsName)); + isMatch = (InStr (resuri, ptouri) >= 0); + } + if (isMatch) + { + std::map imgmap; + for (pugi::xml_node candidate = namedRes.child ("Candidate"); candidate; candidate = candidate.next_sibling ("Candidate")) + { + std::string valueGet = candidate.child ("Value").text ().get (); + for (pugi::xml_node qualifierSet = candidate.child ("QualifierSet"); qualifierSet; qualifierSet = qualifierSet.next_sibling ("QualifierSet")) + { + ImageFileInfo tinfo; + for (pugi::xml_node qualifier = candidate.child ("Qualifier"); qualifier; qualifier = qualifier.next_sibling ("Qualifier")) + { + std::string itemname = qualifier.attribute ("name").as_string (); + if (LabelEqual (itemname, "Contrast")) + { + std::string conText = qualifier.attribute ("value").as_string (); + if (LabelEqual (conText, "BLACK")) tinfo.contrast = ImageContrast::black; + else if (LabelEqual (conText, "WHITE")) tinfo.contrast = ImageContrast::white; + } + else if (LabelEqual (itemname, "Scale")) + { + tinfo.scale = qualifier.attribute ("value").as_int (); + } + } + imgmap [tinfo] = valueGet; + } + } + for (auto it : imgmap) + { + if (defaultContrast == it.first.contrast) + { + if (it.first.scale == defaultScale) + { + LPSTR lpbuf = (LPSTR)calloc (it.second.capacity () + 1, sizeof (char)); + lstrcmpA (lpbuf, it.second.c_str ()); + return lpbuf; + } + } + } + for (auto it : imgmap) + { + if (defaultContrast == it.first.contrast) + { + if (it.first.scale >= defaultScale) + { + LPSTR lpbuf = (LPSTR)calloc (it.second.capacity () + 1, sizeof (char)); + lstrcmpA (lpbuf, it.second.c_str ()); + return lpbuf; + } + } + } + for (auto it : imgmap) + { + if (defaultContrast == it.first.contrast) + { + LPSTR lpbuf = (LPSTR)calloc (it.second.capacity () + 1, sizeof (char)); + lstrcmpA (lpbuf, it.second.c_str ()); + return lpbuf; + } + } + for (auto it : imgmap) + { + if (it.first.contrast == ImageContrast::none) + { + if (it.first.scale == defaultScale) + { + LPSTR lpbuf = (LPSTR)calloc (it.second.capacity () + 1, sizeof (char)); + lstrcmpA (lpbuf, it.second.c_str ()); + return lpbuf; + } + } + } + for (auto it : imgmap) + { + if (it.first.contrast == ImageContrast::none) + { + if (it.first.scale >= defaultScale) + { + LPSTR lpbuf = (LPSTR)calloc (it.second.capacity () + 1, sizeof (char)); + lstrcmpA (lpbuf, it.second.c_str ()); + return lpbuf; + } + } + } + for (auto it : imgmap) + { + if (it.first.contrast == ImageContrast::none) + { + LPSTR lpbuf = (LPSTR)calloc (it.second.capacity () + 1, sizeof (char)); + lstrcmpA (lpbuf, it.second.c_str ()); + return lpbuf; + } + } + for (auto it : imgmap) + { + if (it.first.contrast == ImageContrast::white) + { + if (it.first.scale == defaultScale) + { + LPSTR lpbuf = (LPSTR)calloc (it.second.capacity () + 1, sizeof (char)); + lstrcmpA (lpbuf, it.second.c_str ()); + return lpbuf; + } + } + } + for (auto it : imgmap) + { + if (it.first.contrast == ImageContrast::white) + { + if (it.first.scale >= defaultScale) + { + LPSTR lpbuf = (LPSTR)calloc (it.second.capacity () + 1, sizeof (char)); + lstrcmpA (lpbuf, it.second.c_str ()); + return lpbuf; + } + } + } + for (auto it : imgmap) + { + if (it.first.contrast == ImageContrast::white) + { + LPSTR lpbuf = (LPSTR)calloc (it.second.capacity () + 1, sizeof (char)); + lstrcmpA (lpbuf, it.second.c_str ()); + return lpbuf; + } + } + for (auto it : imgmap) + { + if (it.first.contrast == ImageContrast::black) + { + if (it.first.scale == defaultScale) + { + LPSTR lpbuf = (LPSTR)calloc (it.second.capacity () + 1, sizeof (char)); + lstrcmpA (lpbuf, it.second.c_str ()); + return lpbuf; + } + } + } + for (auto it : imgmap) + { + if (it.first.contrast == ImageContrast::black) + { + if (it.first.scale >= defaultScale) + { + LPSTR lpbuf = (LPSTR)calloc (it.second.capacity () + 1, sizeof (char)); + lstrcmpA (lpbuf, it.second.c_str ()); + return lpbuf; + } + } + } + for (auto it : imgmap) + { + if (it.first.contrast == ImageContrast::black) + { + LPSTR lpbuf = (LPSTR)calloc (it.second.capacity () + 1, sizeof (char)); + lstrcmpA (lpbuf, it.second.c_str ()); + return lpbuf; + } + } + for (auto it : imgmap) + { + LPSTR lpbuf = (LPSTR)calloc (it.second.capacity () + 1, sizeof (char)); + lstrcmpA (lpbuf, it.second.c_str ()); + return lpbuf; + } + } + } + for (pugi::xml_node subtree = subResMap.child ("ResourceMapSubtree"); subtree; subtree = subtree.next_sibling ("ResourceMapSubtree")) + { + LPSTR result = recFindFilePathValue (subtree, lpMsName, defaultScale, defaultContrast); + if (result) return result; // ҵͷ + } + return NULL; + } + LPWSTR recFindFilePathValue (pugi::xml_node &subResMap, LPCWSTR lpMsName, int defaultScale = GetDPI (), ImageContrast defaultContrast = ImageContrast::none) + { + for (pugi::xml_node namedRes = subResMap.child ("NamedResource"); namedRes; namedRes = namedRes.next_sibling ("NamedResource")) + { + bool isMatch = false; + pugi::xml_attribute nameAttr = namedRes.attribute ("name"); + std::wstring resname = pugi::as_wide (nameAttr.as_string ()); + isMatch = LabelEqual (resname, lpMsName); + static const std::wregex pattern (L"^ms-resource:", std::regex_constants::icase); + if (!isMatch) + { + std::wstring lpname2 = std::regex_replace (std::wstring (lpMsName), pattern, L""); + isMatch = LabelEqual (resname, lpname2); + } + if (!isMatch) + { + LPCWSTR filename = PathFindFileNameW (lpMsName); + isMatch = LabelEqual (resname, filename); + } + if (!isMatch) + { + pugi::xml_attribute uriAttr = namedRes.attribute ("uri"); + std::wstring resuri = pugi::as_wide (uriAttr.as_string ()); + std::wstring ptouri = ReplaceBackslash (std::wstring (lpMsName)); + isMatch = (InStr (resuri, ptouri) >= 0); + } + if (isMatch) + { + std::map imgmap; + for (pugi::xml_node candidate = namedRes.child ("Candidate"); candidate; candidate = candidate.next_sibling ("Candidate")) + { + std::wstring valueGet (L""); + valueGet += pugi::as_wide (candidate.child ("Value").text ().get ()); + bool isNoAdd = false; + for (pugi::xml_node qualifierSet = candidate.child ("QualifierSet"); qualifierSet; qualifierSet = qualifierSet.next_sibling ("QualifierSet")) + { + ImageFileInfo tinfo; + for (pugi::xml_node qualifier = qualifierSet.child ("Qualifier"); qualifier; qualifier = qualifier.next_sibling ("Qualifier")) + { + std::string itemname = qualifier.attribute ("name").as_string (); + if (LabelEqual (itemname, "Contrast")) + { + std::string conText = qualifier.attribute ("value").as_string (); + if (LabelEqual (conText, "BLACK")) tinfo.contrast = ImageContrast::black; + else if (LabelEqual (conText, "WHITE")) tinfo.contrast = ImageContrast::white; + else if (LabelEqual (conText, "HIGH")) tinfo.contrast = ImageContrast::white; + } + else if (LabelEqual (itemname, "Scale")) + { + tinfo.scale = qualifier.attribute ("value").as_int (); + } + else if (LabelEqual (itemname, "TargetSize")) + { + tinfo.scale = (int)((double)qualifier.attribute ("value").as_int () * 2); + isNoAdd = true; + } + else if (LabelEqual (itemname, "AlternateForm")) + { + std::string alfText = qualifier.attribute ("value").as_string (); + std::hash hasher; + tinfo.hash = hasher (alfText); + } + } + if (!isNoAdd) if (valueGet.length () > 0) imgmap [tinfo] = valueGet; + } + } + for (auto it : imgmap) + { + if (defaultContrast == it.first.contrast) + { + if (it.first.scale == defaultScale) + { + LPWSTR lpbuf = (LPWSTR)calloc (it.second.capacity () + 1, sizeof (WCHAR)); + StrCpyW (lpbuf, it.second.c_str ()); + return lpbuf; + } + } + } + for (auto it : imgmap) + { + if (defaultContrast == it.first.contrast) + { + if (it.first.scale >= defaultScale) + { + LPWSTR lpbuf = (LPWSTR)calloc (it.second.capacity () + 1, sizeof (WCHAR)); + StrCpyW (lpbuf, it.second.c_str ()); + return lpbuf; + } + } + } + for (auto it : imgmap) + { + if (defaultContrast == it.first.contrast) + { + if (it.first.scale >= 100) + { + LPWSTR lpbuf = (LPWSTR)calloc (it.second.capacity () + 1, sizeof (WCHAR)); + StrCpyW (lpbuf, it.second.c_str ()); + return lpbuf; + } + } + } + for (auto it : imgmap) + { + if (defaultContrast == it.first.contrast) + { + LPWSTR lpbuf = (LPWSTR)calloc (it.second.capacity () + 1, sizeof (WCHAR)); + StrCpyW (lpbuf, it.second.c_str ()); + return lpbuf; + } + } + for (auto it : imgmap) + { + if (it.first.contrast == ImageContrast::none) + { + if (it.first.scale == defaultScale) + { + LPWSTR lpbuf = (LPWSTR)calloc (it.second.capacity () + 1, sizeof (WCHAR)); + StrCpyW (lpbuf, it.second.c_str ()); + return lpbuf; + } + } + } + for (auto it : imgmap) + { + if (it.first.contrast == ImageContrast::none) + { + if (it.first.scale >= defaultScale) + { + LPWSTR lpbuf = (LPWSTR)calloc (it.second.capacity () + 1, sizeof (WCHAR)); + StrCpyW (lpbuf, it.second.c_str ()); + return lpbuf; + } + } + } + for (auto it : imgmap) + { + if (it.first.contrast == ImageContrast::none) + { + if (it.first.scale >= 100) + { + LPWSTR lpbuf = (LPWSTR)calloc (it.second.capacity () + 1, sizeof (WCHAR)); + StrCpyW (lpbuf, it.second.c_str ()); + return lpbuf; + } + } + } + for (auto it : imgmap) + { + if (it.first.contrast == ImageContrast::none) + { + LPWSTR lpbuf = (LPWSTR)calloc (it.second.capacity () + 1, sizeof (WCHAR)); + StrCpyW (lpbuf, it.second.c_str ()); + return lpbuf; + } + } + for (auto it : imgmap) + { + if (it.first.contrast == ImageContrast::white) + { + if (it.first.scale == defaultScale) + { + LPWSTR lpbuf = (LPWSTR)calloc (it.second.capacity () + 1, sizeof (WCHAR)); + StrCpyW (lpbuf, it.second.c_str ()); + return lpbuf; + } + } + } + for (auto it : imgmap) + { + if (it.first.contrast == ImageContrast::white) + { + if (it.first.scale >= defaultScale) + { + LPWSTR lpbuf = (LPWSTR)calloc (it.second.capacity () + 1, sizeof (WCHAR)); + StrCpyW (lpbuf, it.second.c_str ()); + return lpbuf; + } + } + } + for (auto it : imgmap) + { + if (it.first.contrast == ImageContrast::white) + { + if (it.first.scale >= 100) + { + LPWSTR lpbuf = (LPWSTR)calloc (it.second.capacity () + 1, sizeof (WCHAR)); + StrCpyW (lpbuf, it.second.c_str ()); + return lpbuf; + } + } + } + for (auto it : imgmap) + { + if (it.first.contrast == ImageContrast::white) + { + LPWSTR lpbuf = (LPWSTR)calloc (it.second.capacity () + 1, sizeof (WCHAR)); + StrCpyW (lpbuf, it.second.c_str ()); + return lpbuf; + } + } + for (auto it : imgmap) + { + if (it.first.contrast == ImageContrast::black) + { + if (it.first.scale == defaultScale) + { + LPWSTR lpbuf = (LPWSTR)calloc (it.second.capacity () + 1, sizeof (WCHAR)); + StrCpyW (lpbuf, it.second.c_str ()); + return lpbuf; + } + } + } + for (auto it : imgmap) + { + if (it.first.contrast == ImageContrast::black) + { + if (it.first.scale >= defaultScale) + { + LPWSTR lpbuf = (LPWSTR)calloc (it.second.capacity () + 1, sizeof (WCHAR)); + StrCpyW (lpbuf, it.second.c_str ()); + return lpbuf; + } + } + } + for (auto it : imgmap) + { + if (it.first.contrast == ImageContrast::black) + { + if (it.first.scale >= 100) + { + LPWSTR lpbuf = (LPWSTR)calloc (it.second.capacity () + 1, sizeof (WCHAR)); + StrCpyW (lpbuf, it.second.c_str ()); + return lpbuf; + } + } + } + for (auto it : imgmap) + { + if (it.first.contrast == ImageContrast::black) + { + LPWSTR lpbuf = (LPWSTR)calloc (it.second.capacity () + 1, sizeof (WCHAR)); + StrCpyW (lpbuf, it.second.c_str ()); + return lpbuf; + } + } + for (auto it : imgmap) + { + LPWSTR lpbuf = (LPWSTR)calloc (it.second.capacity () + 1, sizeof (WCHAR)); + StrCpyW (lpbuf, it.second.c_str ()); + return lpbuf; + } + } + } + for (pugi::xml_node subtree = subResMap.child ("ResourceMapSubtree"); subtree; subtree = subtree.next_sibling ("ResourceMapSubtree")) + { + LPWSTR result = recFindFilePathValue (subtree, lpMsName, defaultScale, defaultContrast); + if (result) return result; // ҵͷ + } + return NULL; + } + public: + PriReader (LPCWSTR lpPriFilePath) { this->create (lpPriFilePath); } + PriReader (const std::wstring objPriFilePath) { this->create (objPriFilePath); } + PriReader (IStream *comISPriFile) { this->create (comISPriFile); } + ~PriReader () { this->destroy (); } + PriReader (): prifile (L""), txmlpath (L"") { xmlreader = nullptr; } + void destroy () + { + if (xmlreader) delete xmlreader; + xmlreader = nullptr; + if (IsFileExists (txmlpath)) DeleteFileW (txmlpath.c_str ()); + txmlpath = L""; + prifile = L""; + } + bool isAvailable () { return xmlreader != nullptr; } + bool create (const std::wstring priFile) + { + destroy (); + if (!PriReader::initMakePri ()) return false; + std::wstring outputXmlFile; + do + { + outputXmlFile = GetUniqueTempFilePathW () + L".xml"; + } while (IsFileExists (outputXmlFile)); + std::wstring quotedMakepri = L"\"" + makepri + L"\""; + std::wstring quotedPriFile = L"\"" + priFile + L"\""; + std::wstring quotedOutputXmlFile = L"\"" + outputXmlFile + L"\""; + // + std::wstring command = quotedMakepri + L" dump /if " + quotedPriFile + L" /of " + quotedOutputXmlFile + L" /dt detailed"; + // ܵڻȡ stdout + SECURITY_ATTRIBUTES sa; + sa.nLength = sizeof (SECURITY_ATTRIBUTES); + sa.bInheritHandle = TRUE; // ӽ̼̳о + sa.lpSecurityDescriptor = nullptr; + HANDLE hReadPipe, hWritePipe; + if (!CreatePipe (&hReadPipe, &hWritePipe, &sa, 0)) + { + return false; // ܵʧ + } + STARTUPINFO si = {sizeof (si)}; + PROCESS_INFORMATION pi = {0}; + si.dwFlags = STARTF_USESTDHANDLES; + si.hStdOutput = hWritePipe; // ض׼ + si.hStdError = hWritePipe; // ض + si.hStdInput = NULL; + // ִ + if (CreateProcessW (nullptr, const_cast(command.c_str ()), nullptr, nullptr, TRUE, CREATE_NO_WINDOW, nullptr, nullptr, &si, &pi)) + { + CloseHandle (hWritePipe); // رдˣֹ ReadFile + std::wstring output; + CHAR buffer [4098]; // ȡ + DWORD bytesRead; + while (ReadFile (hReadPipe, buffer, sizeof (buffer) - 1, &bytesRead, nullptr) && bytesRead > 0) + { + buffer [bytesRead] = '\0'; // ȷַֹ + output += (WCHAR *)buffer; + ZeroMemory (buffer, 4098); + } + // ϢANSI 棩 + // ȴ̽ + WaitForSingleObject (pi.hProcess, INFINITE); + while (ReadFile (hReadPipe, buffer, sizeof (buffer) - 1, &bytesRead, nullptr) && bytesRead > 0) + { + buffer [bytesRead] = '\0'; // ȷַֹ + output += (WCHAR *)buffer; + ZeroMemory (buffer, 4098); + } + CloseHandle (hReadPipe); + std::wstring debugoutput (L""); + debugoutput += L"Command Line:\n" + command + L"\n"; + debugoutput += L"Process Output:\n" + output + L"\n"; + OutputDebugStringW (debugoutput.c_str ()); + // ļǷ + if (IsFileExists (outputXmlFile)) + { + CloseHandle (pi.hProcess); + CloseHandle (pi.hThread); + } + else + { + CloseHandle (pi.hProcess); + CloseHandle (pi.hThread); + return false; // ʧ + } + } + else + { + CloseHandle (hReadPipe); + CloseHandle (hWritePipe); + return false; // ̴ʧ + } + txmlpath = outputXmlFile; + xmlreader = new pugi::xml_document (); + if (!xmlreader->load_file (outputXmlFile.c_str ())) + { + this->destroy (); + return false; + } + return true; + } + bool create (LPCWSTR priFile) { destroy (); if (!priFile) return false; return this->create (std::wstring (priFile)); } + bool create (IStream *priFStream) + { + destroy (); + if (!PriReader::initMakePri ()) return false; + if (!priFStream) return false; + std::wstring tempPriFile; + do + { + tempPriFile = GetUniqueTempFilePathW () + L".pri"; + } while (IsFileExists (tempPriFile)); + HRESULT hr = ExtractFileFromStream (priFStream, tempPriFile.c_str ()); + if (FAILED (hr)) + { + if (IsFileExists (tempPriFile)) DeleteFileW (tempPriFile.c_str ()); + return false; + } + bool res = this->create (tempPriFile); + DeleteFileW (tempPriFile.c_str ()); + return res; + } + // ȡָҪ free ֶͷš + LPSTR findStringValue (LPCSTR lpMsName, LPCSTR defaultLocaleCode = LcidToLocaleCodeA (GetUserDefaultLCID ()).c_str ()) + { + pugi::xml_node root = xmlreader->child ("PriInfo"); + if (!root) return NULL; + pugi::xml_node resmap = root.child ("ResourceMap"); + if (!resmap) return NULL; + resmap.child ("ResourceMapSubtree"); + for (pugi::xml_node subtree = resmap.child ("ResourceMapSubtree"); subtree; subtree = subtree.next_sibling ("ResourceMapSubtree")) + { + std::string resMapName = subtree.attribute ("name").as_string (); + if (!LabelEqual (resMapName, "resources")) continue; + LPSTR result = recFindStringValue (subtree, lpMsName, defaultLocaleCode); + if (result) return result; + } + return NULL; + } + // ȡָҪ free ֶͷš + LPWSTR findStringValue (LPCWSTR lpMsName, LPCWSTR defaultLocaleCode = LcidToLocaleCodeW (GetUserDefaultLCID ()).c_str ()) + { + pugi::xml_node root = xmlreader->child ("PriInfo"); + if (!root) return NULL; + pugi::xml_node resmap = root.child ("ResourceMap"); + if (!resmap) return NULL; + for (pugi::xml_node subtree = resmap.child ("ResourceMapSubtree"); subtree; subtree = subtree.next_sibling ("ResourceMapSubtree")) + { + std::string resMapName = subtree.attribute ("name").as_string (); + if (LabelEqual (resMapName, "Files")) continue; + // if (!LabelEqual (resMapName, "resources")) continue; + LPWSTR result = recFindStringValue (subtree, lpMsName, defaultLocaleCode); + if (result && lstrlenW (result) > 0) return result; + } + return NULL; + } + std::string findStringValue (const std::string &objMsName, const std::string &defaultLocaleCode = LcidToLocaleCodeA (GetUserDefaultLCID ())) + { + std::string t (""); + LPSTR lpStr = findStringValue (objMsName.c_str (), defaultLocaleCode.c_str ()); + if (lpStr) t += lpStr; + if (lpStr) free (lpStr); + return t; + } + std::wstring findStringValue (const std::wstring &objMsName, const std::wstring &defaultLocaleCode = LcidToLocaleCodeW (GetUserDefaultLCID ())) + { + std::wstring t (L""); + LPWSTR lpStr = findStringValue (objMsName.c_str (), defaultLocaleCode.c_str ()); + if (lpStr) t += lpStr; + if (lpStr) free (lpStr); + return t; + } + LPSTR findFilePathValue (LPCSTR lpMsName, int defaultScale = GetDPI (), ImageContrast defaultContrast = ImageContrast::none) + { + pugi::xml_node root = xmlreader->child ("PriInfo"); + if (!root) return NULL; + pugi::xml_node resmap = root.child ("ResourceMap"); + if (!resmap) return NULL; + resmap.child ("ResourceMapSubtree"); + for (pugi::xml_node subtree = resmap.child ("ResourceMapSubtree"); subtree; subtree = subtree.next_sibling ("ResourceMapSubtree")) + { + std::string resMapName = subtree.attribute ("name").as_string (); + if (!LabelEqual (resMapName, "Files")) continue; + LPSTR result = recFindFilePathValue (subtree, lpMsName, defaultScale, defaultContrast); + if (result) return result; + } + return NULL; + } + LPWSTR findFilePathValue (LPCWSTR lpMsName, int defaultScale = GetDPI (), ImageContrast defaultContrast = ImageContrast::none) + { + pugi::xml_node root = xmlreader->child ("PriInfo"); + if (!root) return NULL; + pugi::xml_node resmap = root.child ("ResourceMap"); + if (!resmap) return NULL; + resmap.child ("ResourceMapSubtree"); + for (pugi::xml_node subtree = resmap.child ("ResourceMapSubtree"); subtree; subtree = subtree.next_sibling ("ResourceMapSubtree")) + { + std::string resMapName = subtree.attribute ("name").as_string (); + if (!LabelEqual (resMapName, "Files")) continue; + LPWSTR result = recFindFilePathValue (subtree, lpMsName, defaultScale, defaultContrast); + if (result) return result; + } + return NULL; + } + std::string findFilePathValue (const std::string &objMsName, int defaultScale = GetDPI (), ImageContrast defaultContrast = ImageContrast::none) + { + std::string t (""); + LPSTR lpStr = findFilePathValue (objMsName.c_str (), defaultScale, defaultContrast); + if (lpStr) t += lpStr; + if (lpStr) free (lpStr); + return t; + } + std::wstring findFilePathValue (const std::wstring &objMsName, int defaultScale = GetDPI (), ImageContrast defaultContrast = ImageContrast::none) + { + std::wstring t (L""); + LPWSTR lpStr = findFilePathValue (objMsName.c_str (), defaultScale, defaultContrast); + if (lpStr) t += lpStr; + if (lpStr) free (lpStr); + return t; + } +}; +std::wstring PriReader::makepri = L""; + +HPRIREADER CreatePriReader (LPCWSTR priFilePath) +{ + if (!priFilePath) return NULL; + PriReader *ptr = new PriReader (); + bool res = ptr->create (priFilePath); + if (!res) + { + delete ptr; + return NULL; + } + return ptr; +} +HPRIREADER CreatePriReaderFromStream (HISTREAM isPriFile) +{ + if (!isPriFile) return NULL; + PriReader *ptr = new PriReader (); + bool res = ptr->create ((IStream *)isPriFile); + if (!res) + { + delete ptr; + return NULL; + } + return ptr; +} +void DestroyPriReader (HPRIREADER hpr) +{ + if (!hpr) return; + PriReader *ptr = (PriReader *)hpr; + delete hpr; + return; +} +// صַֻܿ϶ǿַȷı뷽ʽΪ ANSI ҲпΪ UTF-8 +// ȡֶַͷţ free () +LPSTR PriReaderFindStringValueA (HPRIREADER hPriReader, LPCSTR lpMsName, LPCSTR lpDefaultLocaleCode) +{ + if (!hPriReader || !lpMsName) return NULL; + PriReader *ptr = (PriReader *)hPriReader; + if (lpDefaultLocaleCode) return ptr->findStringValue (lpMsName, lpDefaultLocaleCode); + else return ptr->findStringValue (lpMsName); +} +LPWSTR PriReaderFindStringValueW (HPRIREADER hPriReader, LPCWSTR lpMsName, LPCWSTR lpDefaultLocaleCode) +{ + if (!hPriReader || !lpMsName) return NULL; + PriReader *ptr = (PriReader *)hPriReader; + if (lpDefaultLocaleCode) return ptr->findStringValue (lpMsName, lpDefaultLocaleCode); + else return ptr->findStringValue (lpMsName); +} +LPSTR PriReaderFindFilePathValueA (HPRIREADER hPriReader, LPCSTR lpMsName, int defaultScale, ImageContrast defaultContrast) +{ + if (!hPriReader || !lpMsName) return NULL; + PriReader *ptr = (PriReader *)hPriReader; + if (defaultScale <= 0) defaultScale = GetDPI (); + if ((int)defaultContrast) defaultContrast = ImageContrast::none; + return ptr->findFilePathValue (lpMsName, defaultScale, defaultContrast); +} +LPWSTR PriReaderFindFilePathValueW (HPRIREADER hPriReader, LPCWSTR lpMsName, int defaultScale, ImageContrast defaultContrast) +{ + if (!hPriReader || !lpMsName) return NULL; + PriReader *ptr = (PriReader *)hPriReader; + if (defaultScale <= 0) defaultScale = GetDPI (); + if ((int)defaultContrast) defaultContrast = ImageContrast::none; + return ptr->findFilePathValue (lpMsName, defaultScale, defaultContrast); +} diff --git a/PriReader2/PriReader2.h b/PriReader2/PriReader2.h new file mode 100644 index 0000000..263a6b4 --- /dev/null +++ b/PriReader2/PriReader2.h @@ -0,0 +1,69 @@ +// ifdef Ǵʹ DLL 򵥵 +// ı׼ DLL еļ϶ PRIREADER2_EXPORTS +// űġʹô DLL +// κĿϲӦ˷šԴļаļκĿὫ +// PRIREADER2_API ΪǴ DLL ģ DLL ô˺궨 +// ΪDZġ +#ifdef PRIREADER2_EXPORTS +#define PRIREADER2_API __declspec(dllexport) +#else +#define PRIREADER2_API __declspec(dllimport) +#endif + +#define class_prireader2 class PRIREADER2_API +#define struct_prireader2 struct PRIREADER2_API +#define enum_prireader2 enum PRIREADER2_API +#define enum_class_prireader2 enum class PRIREADER2_API +#define func_prireader2 PRIREADER2_API +#define func_c_prireader2 extern "C" func_prireader2 + +func_c_prireader2 int GetDPI (); +func_c_prireader2 bool IsDirectoryExistsA (LPCSTR path); +func_c_prireader2 bool IsDirectoryExistsW (LPCWSTR path); + +// ͼʹáʾڸ߶ԱȶӦ +enum_class_prireader2 ImageContrast +{ + none = 0, // ָʾ߶Աȶ + white = 1, // ڸ߶ԱȶȺɫͼƬdzɫ + black = 2, // ڸ߶ԱȶȰɫͼƬɫ + high = 3 // ߶Աȶȣ̫ +}; + +typedef HANDLE HPRIREADER; +typedef HANDLE HISTREAM; // IStream * + +func_c_prireader2 HPRIREADER CreatePriReader (LPCWSTR priFilePath); +func_c_prireader2 HPRIREADER CreatePriReaderFromStream (HISTREAM isPriFile); +func_c_prireader2 void DestroyPriReader (HPRIREADER hpr); +// صַֻܿ϶ǿַȷı뷽ʽΪ ANSI ҲпΪ UTF-8 +// ȡֶַͷţ free () +func_c_prireader2 LPSTR PriReaderFindStringValueA ( + HPRIREADER hPriReader, + LPCSTR lpMsName, + LPCSTR lpDefaultLocaleCode // NULLʹĬԴ +); +// صַֻܿ϶ǿַȷı뷽ʽΪ ANSI ҲпΪ UTF-8 +// ȡֶַͷţ free () +func_c_prireader2 LPWSTR PriReaderFindStringValueW ( + HPRIREADER hPriReader, + LPCWSTR lpMsName, + LPCWSTR lpDefaultLocaleCode // NULLʹĬԴ +); +// صַֻܿ϶ǿַȷı뷽ʽΪ ANSI ҲпΪ UTF-8 +// ȡֶַͷţ free () +func_c_prireader2 LPSTR PriReaderFindFilePathValueA ( + HPRIREADER hPriReader, + LPCSTR lpMsName, + int defaultScale, // NULLʹĬ DPI DPIͨʾΪ 100 + ImageContrast defaultContrast +); +// صַֻܿ϶ǿַȷı뷽ʽΪ ANSI ҲпΪ UTF-8 +// ȡֶַͷţ free () +func_c_prireader2 LPWSTR PriReaderFindFilePathValueW ( + HPRIREADER hPriReader, + LPCWSTR lpMsName, + int defaultScale, // NULLʹĬ DPI DPIͨʾΪ 100 + ImageContrast defaultContrast +); + diff --git a/PriReader2/PriReader2.vcxproj b/PriReader2/PriReader2.vcxproj new file mode 100644 index 0000000..cedcd0a --- /dev/null +++ b/PriReader2/PriReader2.vcxproj @@ -0,0 +1,265 @@ + + + + + Debug + ARM + + + Debug + Win32 + + + Release + ARM + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {B897969C-6EA9-4DFC-B7E0-94F1C6D94856} + Win32Proj + PriReader2 + 8.1 + + + + DynamicLibrary + true + v140 + Unicode + + + DynamicLibrary + true + v140 + Unicode + + + DynamicLibrary + false + v140 + true + Unicode + + + DynamicLibrary + false + v140 + true + Unicode + + + DynamicLibrary + true + v140 + Unicode + + + DynamicLibrary + false + v140 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + true + + + true + + + false + + + false + + + false + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;PRIREADER2_EXPORTS;%(PreprocessorDefinitions) + true + + + Windows + true + Shlwapi.lib;%(AdditionalDependencies) + + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;PRIREADER2_EXPORTS;%(PreprocessorDefinitions) + true + + + Windows + true + Shlwapi.lib;%(AdditionalDependencies) + + + + + Use + Level3 + Disabled + _DEBUG;_WINDOWS;_USRDLL;PRIREADER2_EXPORTS;%(PreprocessorDefinitions) + true + + + Windows + true + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;PRIREADER2_EXPORTS;%(PreprocessorDefinitions) + true + MultiThreadedDLL + + + Windows + true + true + true + Shlwapi.lib;%(AdditionalDependencies) + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;PRIREADER2_EXPORTS;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + Shlwapi.lib;%(AdditionalDependencies) + + + + + Level3 + Use + MaxSpeed + true + true + NDEBUG;_WINDOWS;_USRDLL;PRIREADER2_EXPORTS;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + + + + + + + + + + + + + + false + false + + + + + false + + + false + false + + + + + false + + + + + + Create + Create + Create + Create + Create + Create + + + + + + + + + + + + 这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。 + + + + \ No newline at end of file diff --git a/PriReader2/PriReader2.vcxproj.filters b/PriReader2/PriReader2.vcxproj.filters new file mode 100644 index 0000000..20159b0 --- /dev/null +++ b/PriReader2/PriReader2.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/PriReader2/ReadMe.txt b/PriReader2/ReadMe.txt new file mode 100644 index 0000000..86c89d4 --- /dev/null +++ b/PriReader2/ReadMe.txt @@ -0,0 +1,30 @@ +======================================================================== + 动态链接库:PriReader2 项目概述 +======================================================================== + +应用程序向导已为您创建了此 PriReader2 DLL。 + +本文件概要介绍组成 PriReader2 应用程序的每个文件的内容。 + + +PriReader2.vcxproj + 这是使用应用程序向导生成的 VC++ 项目的主项目文件,其中包含生成该文件的 Visual C++ 的版本信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。 + +PriReader2.vcxproj.filters + 这是使用“应用程序向导”生成的 VC++ 项目筛选器文件。它包含有关项目文件与筛选器之间的关联信息。在 IDE 中,通过这种关联,在特定节点下以分组形式显示具有相似扩展名的文件。例如,“.cpp”文件与“源文件”筛选器关联。 + +PriReader2.cpp + 这是主 DLL 源文件。 + +///////////////////////////////////////////////////////////////////////////// +其他标准文件: + +StdAfx.h, StdAfx.cpp + 这些文件用于生成名为 PriReader2.pch 的预编译头 (PCH) 文件和名为 StdAfx.obj 的预编译类型文件。 + +///////////////////////////////////////////////////////////////////////////// +其他注释: + +应用程序向导使用“TODO:”注释来指示应添加或自定义的源代码部分。 + +///////////////////////////////////////////////////////////////////////////// diff --git a/PriReader2/dllmain.cpp b/PriReader2/dllmain.cpp new file mode 100644 index 0000000..260abc6 --- /dev/null +++ b/PriReader2/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/PriReader2/localeex.h b/PriReader2/localeex.h new file mode 100644 index 0000000..458d6a3 --- /dev/null +++ b/PriReader2/localeex.h @@ -0,0 +1,108 @@ +#pragma once +#include "stdafx.h" + +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; +} + +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; +} +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; +} +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 ()); +} +std::string GetLocaleRestrictedCodeFromLcidA (LCID lcid) +{ + return GetLocaleInfoA (lcid, 89); +} +std::wstring GetLocaleRestrictedCodeFromLcidW (LCID lcid) +{ + return GetLocaleInfoW (lcid, 89); +} +std::string GetLocaleElaboratedCodeFromLcidA (LCID lcid) +{ + return GetLocaleInfoA (lcid, 90); +} +std::wstring GetLocaleElaboratedCodeFromLcidW (LCID lcid) +{ + return GetLocaleInfoW (lcid, 90); +} +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 ()); +} +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::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::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); +} diff --git a/PriReader2/packages.config b/PriReader2/packages.config new file mode 100644 index 0000000..c2da1c1 --- /dev/null +++ b/PriReader2/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/PriReader2/stdafx.cpp b/PriReader2/stdafx.cpp new file mode 100644 index 0000000..f6667da --- /dev/null +++ b/PriReader2/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : ֻ׼ļԴļ +// PriReader2.pch ΪԤͷ +// stdafx.obj ԤϢ + +#include "stdafx.h" + +// TODO: STDAFX.H κĸͷļ +//ڴļ diff --git a/PriReader2/stdafx.h b/PriReader2/stdafx.h new file mode 100644 index 0000000..b70eab5 --- /dev/null +++ b/PriReader2/stdafx.h @@ -0,0 +1,30 @@ +// 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 +using namespace std; \ No newline at end of file diff --git a/PriReader2/targetver.h b/PriReader2/targetver.h new file mode 100644 index 0000000..416cebf --- /dev/null +++ b/PriReader2/targetver.h @@ -0,0 +1,8 @@ +#pragma once + +// SDKDDKVer.h õ߰汾 Windows ƽ̨ + +// ҪΪǰ Windows ƽ̨Ӧó WinSDKVer.h +// _WIN32_WINNT ΪҪֵ֧ƽ̨Ȼٰ SDKDDKVer.h + +#include diff --git a/README.md b/README.md new file mode 100644 index 0000000..26d5ab2 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# AppInstallerForWin8 +A Windows Store App Installer for Windows 8. diff --git a/ShoutcutCreater/AddPackageSample.cpp b/ShoutcutCreater/AddPackageSample.cpp new file mode 100644 index 0000000..0019257 --- /dev/null +++ b/ShoutcutCreater/AddPackageSample.cpp @@ -0,0 +1,34 @@ +//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +//// PARTICULAR PURPOSE. +//// +//// Copyright (c) Microsoft Corporation. All rights reserved + +#include "stdafx.h" +#include "PackageManager.h" +#include +using namespace std; +void callback (unsigned progress) +{ + std::cout << '\r' << progress << "%" << std::ends; +} + +[MTAThread] +int __cdecl main(Platform::Array^ args) +{ + wcout << L"Copyright (c) Microsoft Corporation. All rights reserved." << endl; + wcout << L"Add Package" << endl << endl; + + if (args->Length < 2) + { + wcout << L"Usage: addpkg.exe packageUri" << endl; + return 1; + } + HANDLE completedEvent = nullptr; + int returnValue = 0; + String^ inputPackageUri = args[1]; + cout << endl; + AddPackageFromPath (inputPackageUri->Data (), &callback); + return 0; +} diff --git a/ShoutcutCreater/README.txt b/ShoutcutCreater/README.txt new file mode 100644 index 0000000..09ff1df --- /dev/null +++ b/ShoutcutCreater/README.txt @@ -0,0 +1,39 @@ +Add Package Sample +==================== +This sample demonstrates how to use IPackageManager to install a package. + +Prerequisites +============= +This sample requires Windows 8.1+. +This sample requires Visual Studio 12 Ultimate Developer Preview. +This sample requires the Windows Runtime Software Development Kit. + +Sample Language Implementations +=============================== +C++ + +Files: +====== +AddPackageSample.cpp + +To build the sample using the command prompt: +============================================= + 1. Open the Command Prompt window and navigate to the directory. + 2. Type msbuild AddPackageSample.sln. + + +To build the sample using Visual Studio 12 Ultimate Developer Preview (preferred method): +================================================ + 1. Open File Explorer and navigate to the directory. + 2. Double-click the icon for the .sln (solution) file to open the file in + Visual Studio. + 3. In the Build menu, select Build Solution. The application will be + built in the default \Debug or \Release directory. + + +To Run the sample: +================== + 1. Open a command prompt. + 2. Navigate to the directory containing AddPackageSample.exe + 2. Type AddPackageSample.exe "" at the command line. + For example, AddPackageSample.exe "file://C|/users/testuser/desktop/testpackage.appx" diff --git a/ShoutcutCreater/ShortcutCreater.cpp b/ShoutcutCreater/ShortcutCreater.cpp new file mode 100644 index 0000000..b016ff0 --- /dev/null +++ b/ShoutcutCreater/ShortcutCreater.cpp @@ -0,0 +1,46 @@ +#include "stdafx.h" +#include "Shortcut\tCreater.h" + +HRESULT CreateShortcut (LPCWSTR shortcutPath, LPCWSTR targetPath, LPCWSTR appUserModelID) +{ + HRESULT hr; + IShellLink* psl = nullptr; + IPersistFile* ppf = nullptr; + IPropertyStore* pps = nullptr; + PROPVARIANT pv; + hr = CoInitializeEx (nullptr, COINIT_APARTMENTTHREADED); + if (FAILED (hr)) + return hr; + // Create a ShellLink object + hr = CoCreateInstance (CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&psl); + if (SUCCEEDED (hr)) + { + // Set the path to the shortcut target + psl->SetPath (targetPath); + // Set the AppUserModelID property for the shortcut + hr = psl->QueryInterface (IID_IPropertyStore, (void**)&pps); + if (SUCCEEDED (hr)) + { + hr = InitPropVariantFromString (appUserModelID, &pv); + if (SUCCEEDED (hr)) + { + hr = pps->SetValue (PKEY_AppUserModel_ID, pv); + if (SUCCEEDED (hr)) + { + hr = pps->Commit (); + } + PropVariantClear (&pv); + } + pps->Release (); + } + // Save the shortcut to disk + hr = psl->QueryInterface (IID_IPersistFile, (void**)&ppf); + if (SUCCEEDED (hr)) + { + hr = ppf->Save (shortcutPath, TRUE); + ppf->Release (); + } + psl->Release (); + } + return hr; +} \ No newline at end of file diff --git a/ShoutcutCreater/ShortcutCreater.h b/ShoutcutCreater/ShortcutCreater.h new file mode 100644 index 0000000..9f39361 --- /dev/null +++ b/ShoutcutCreater/ShortcutCreater.h @@ -0,0 +1,10 @@ +#pragma once +#ifdef SHORTCUT_EXPORTS +#define SHORUTCUT_API __declspec(dllexport) +#else +#define SHORUTCUT_API __declspec(dllimport) +#endif + +#include + +extern "C" SHORUTCUT_API HRESULT CreateShortcut (LPCWSTR shortcutPath, LPCWSTR targetPath, LPCWSTR appUserModelID); diff --git a/ShoutcutCreater/ShortcutCreater.sln b/ShoutcutCreater/ShortcutCreater.sln new file mode 100644 index 0000000..e25c5fe --- /dev/null +++ b/ShoutcutCreater/ShortcutCreater.sln @@ -0,0 +1,22 @@ + +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}") = "ShortcutCreater", "ToastNotification.vcxproj", "{E10C6272-B876-4DC6-9E13-7CA646863B50}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E10C6272-B876-4DC6-9E13-7CA646863B50}.Debug|Win32.ActiveCfg = Debug|Win32 + {E10C6272-B876-4DC6-9E13-7CA646863B50}.Debug|Win32.Build.0 = Debug|Win32 + {E10C6272-B876-4DC6-9E13-7CA646863B50}.Release|Win32.ActiveCfg = Release|Win32 + {E10C6272-B876-4DC6-9E13-7CA646863B50}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/ShoutcutCreater/ToastNotification.vcxproj b/ShoutcutCreater/ToastNotification.vcxproj new file mode 100644 index 0000000..8e22a15 --- /dev/null +++ b/ShoutcutCreater/ToastNotification.vcxproj @@ -0,0 +1,101 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + $(VCTargetsPath11) + 12.0 + + + Win32Proj + {E10C6272-B876-4DC6-9E13-7CA646863B50} + ShortcutCreater + + + + DynamicLibrary + true + v120 + Unicode + + + DynamicLibrary + false + v120 + Unicode + + + + + + + + + + + + + false + $(VCINSTALLDIR)\vcpackages;$(VCInstallDir)atlmfc\lib;$(VCInstallDir)lib;$(WindowsSdkDir)\References\CommonConfiguration\Neutral + + + false + $(VCINSTALLDIR)\vcpackages;$(VCInstallDir)atlmfc\lib;$(VCInstallDir)lib;$(WindowsSdkDir)\References\CommonConfiguration\Neutral + + + + WIN32;_DEBUG;SHORTCUT_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + Level3 + ProgramDatabase + Disabled + true + false + /ZW:nostdlib /FUplatform.winmd /FUwindows.winmd %(AdditionalOptions) + Create + + + MachineX86 + true + NotSet + + + + + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + Level3 + ProgramDatabase + true + /ZW:nostdlib /FUplatform.winmd /FUWindows.winmd %(AdditionalOptions) + + + MachineX86 + true + Console + true + true + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ShoutcutCreater/stdafx.h b/ShoutcutCreater/stdafx.h new file mode 100644 index 0000000..e8d731e --- /dev/null +++ b/ShoutcutCreater/stdafx.h @@ -0,0 +1,5 @@ +#pragma once +#include +#include +#include +#include diff --git a/ToastNotification/AddPackageSample.cpp b/ToastNotification/AddPackageSample.cpp new file mode 100644 index 0000000..0019257 --- /dev/null +++ b/ToastNotification/AddPackageSample.cpp @@ -0,0 +1,34 @@ +//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +//// PARTICULAR PURPOSE. +//// +//// Copyright (c) Microsoft Corporation. All rights reserved + +#include "stdafx.h" +#include "PackageManager.h" +#include +using namespace std; +void callback (unsigned progress) +{ + std::cout << '\r' << progress << "%" << std::ends; +} + +[MTAThread] +int __cdecl main(Platform::Array^ args) +{ + wcout << L"Copyright (c) Microsoft Corporation. All rights reserved." << endl; + wcout << L"Add Package" << endl << endl; + + if (args->Length < 2) + { + wcout << L"Usage: addpkg.exe packageUri" << endl; + return 1; + } + HANDLE completedEvent = nullptr; + int returnValue = 0; + String^ inputPackageUri = args[1]; + cout << endl; + AddPackageFromPath (inputPackageUri->Data (), &callback); + return 0; +} diff --git a/ToastNotification/README.txt b/ToastNotification/README.txt new file mode 100644 index 0000000..09ff1df --- /dev/null +++ b/ToastNotification/README.txt @@ -0,0 +1,39 @@ +Add Package Sample +==================== +This sample demonstrates how to use IPackageManager to install a package. + +Prerequisites +============= +This sample requires Windows 8.1+. +This sample requires Visual Studio 12 Ultimate Developer Preview. +This sample requires the Windows Runtime Software Development Kit. + +Sample Language Implementations +=============================== +C++ + +Files: +====== +AddPackageSample.cpp + +To build the sample using the command prompt: +============================================= + 1. Open the Command Prompt window and navigate to the directory. + 2. Type msbuild AddPackageSample.sln. + + +To build the sample using Visual Studio 12 Ultimate Developer Preview (preferred method): +================================================ + 1. Open File Explorer and navigate to the directory. + 2. Double-click the icon for the .sln (solution) file to open the file in + Visual Studio. + 3. In the Build menu, select Build Solution. The application will be + built in the default \Debug or \Release directory. + + +To Run the sample: +================== + 1. Open a command prompt. + 2. Navigate to the directory containing AddPackageSample.exe + 2. Type AddPackageSample.exe "" at the command line. + For example, AddPackageSample.exe "file://C|/users/testuser/desktop/testpackage.appx" diff --git a/ToastNotification/ToastNotification.cpp b/ToastNotification/ToastNotification.cpp new file mode 100644 index 0000000..8dfccf6 --- /dev/null +++ b/ToastNotification/ToastNotification.cpp @@ -0,0 +1,226 @@ +#include "stdafx.h" +#include "ToastNotification.h" + +bool SaveIStreamToTempFile (IStream* stream, wchar_t* tempFilePath, size_t pathLen) +{ + wchar_t tempPath [MAX_PATH]; + if (!GetTempPathW (MAX_PATH, tempPath)) return false; + if (!GetTempFileNameW (tempPath, L"TST", 0, tempFilePath)) return false; + std::ofstream outFile (tempFilePath, std::ios::binary); + if (!outFile) return false; + // ȡ IStream + STATSTG stat; + HRESULT hr = stream->Stat (&stat, STATFLAG_NONAME); + if (FAILED (hr)) return false; + LARGE_INTEGER liZero = {}; + stream->Seek (liZero, STREAM_SEEK_SET, nullptr); + ULARGE_INTEGER remaining = stat.cbSize; + BYTE buffer [4096]; + ULONG bytesRead; + while (remaining.QuadPart > 0) + { + hr = stream->Read (buffer, min (sizeof (buffer), remaining.LowPart), &bytesRead); + if (FAILED (hr) || bytesRead == 0) break; + outFile.write ((char*)buffer, bytesRead); + remaining.QuadPart -= bytesRead; + } + return outFile.good (); +} + +// ̰߳ȫɾʱļ +void DeleteFileThreadSafe (wchar_t* filePath) +{ + Sleep (5000); // ȴ֪ͨʾ + DeleteFileW (filePath); +} + +bool CreateToastNotification ( + LPCWSTR identityName, + LPCWSTR title, + LPCWSTR text, + NOTICE_PRESS_CALLBACK callback, + HISTREAM imgFile +) +{ + ComPtr notifier; + ComPtr toast; + ComPtr toastFactory; + ComPtr xmlDoc; + HRESULT hr = RoInitialize (RO_INIT_MULTITHREADED); + if (FAILED (hr) && hr != RPC_E_CHANGED_MODE) return false; + ComPtr toastManager; + hr = RoGetActivationFactory (HStringReference (L"Windows.UI.Notifications.ToastNotificationManager").Get (), + __uuidof(IToastNotificationManagerStatics), + &toastManager); + if (FAILED (hr)) return false; + hr = toastManager->CreateToastNotifierWithId (HStringReference (identityName).Get (), ¬ifier); + if (FAILED (hr)) return false; + hr = RoActivateInstance (HStringReference (L"Windows.Data.Xml.Dom.XmlDocument").Get (), &xmlDoc); + if (FAILED (hr)) return false; + wchar_t xmlTemplateWithImage [] = + L"" + L"" + L"" + L"" + L"%s" + L"%s" + L"" + L"" + L""; + wchar_t xmlTemplateNoImage [] = + L"" + L"" + L"" + L"%s" + L"%s" + L"" + L"" + L""; + wchar_t xmlData [1024]; + wchar_t imagePath [MAX_PATH] = L""; + if (imgFile != NULL) + { + IStream* img = (IStream*)imgFile; + STATSTG stat; + hr = img->Stat (&stat, STATFLAG_DEFAULT); + if (SUCCEEDED (hr) && stat.pwcsName) + { + wcscpy_s (imagePath, stat.pwcsName); + CoTaskMemFree (stat.pwcsName); + } + else + { + if (!SaveIStreamToTempFile (img, imagePath, MAX_PATH)) return false; + wchar_t* tempFileCopy = _wcsdup (imagePath); + if (tempFileCopy) + { + CreateThread (nullptr, 0, (LPTHREAD_START_ROUTINE)DeleteFileThreadSafe, tempFileCopy, 0, nullptr); + } + } + swprintf_s (xmlData, xmlTemplateWithImage, imagePath, title, text); + } + else + { + swprintf_s (xmlData, xmlTemplateNoImage, title, text); + } + ComPtr xmlDocIO; + hr = xmlDoc.As (&xmlDocIO); + if (FAILED (hr)) return false; + hr = xmlDocIO->LoadXml (HStringReference (xmlData).Get ()); + if (FAILED (hr)) return false; + hr = RoGetActivationFactory (HStringReference (L"Windows.UI.Notifications.ToastNotification").Get (), + __uuidof(IToastNotificationFactory), + &toastFactory); + if (FAILED (hr)) return false; + hr = toastFactory->CreateToastNotification (xmlDoc.Get (), &toast); + if (FAILED (hr)) return false; + return SUCCEEDED (notifier->Show (toast.Get ())); +} + +HRESULT CreateShortcutWithAppIdA (LPCSTR pszShortcutPath, LPCSTR pszTargetPath, LPCSTR pszAppId) +{ + HRESULT hr; + // ʼ COM + hr = CoInitialize (NULL); + if (FAILED (hr)) + return hr; + // IShellLink ANSI汾 + IShellLinkA* pShellLinkA = NULL; + hr = CoCreateInstance (CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, + IID_IShellLinkA, (void**)&pShellLinkA); + if (FAILED (hr)) + { + CoUninitialize (); + return hr; + } + // ÿݷʽĿ· + hr = pShellLinkA->SetPath (pszTargetPath); + if (FAILED (hr)) + { + pShellLinkA->Release (); + CoUninitialize (); + return hr; + } + // AppUserModelID + IPropertyStore* pPropStore = NULL; + hr = pShellLinkA->QueryInterface (IID_IPropertyStore, (void**)&pPropStore); + if (SUCCEEDED (hr)) + { + PROPVARIANT propvar; + hr = InitPropVariantFromString (_bstr_t (pszAppId), &propvar); + if (SUCCEEDED (hr)) + { + // PKEY_AppUserModel_ID propkey.h + hr = pPropStore->SetValue (PKEY_AppUserModel_ID, propvar); + if (SUCCEEDED (hr)) + hr = pPropStore->Commit (); + PropVariantClear (&propvar); + } + pPropStore->Release (); + } + // ݷʽļIPersistFile Ҫַ + IPersistFile* pPersistFile = NULL; + hr = pShellLinkA->QueryInterface (IID_IPersistFile, (void**)&pPersistFile); + if (SUCCEEDED (hr)) + { + // pszShortcutPath ANSI תΪ Unicode + wchar_t wszShortcutPath [MAX_PATH]; + MultiByteToWideChar (CP_ACP, 0, pszShortcutPath, -1, wszShortcutPath, MAX_PATH); + hr = pPersistFile->Save (wszShortcutPath, TRUE); + pPersistFile->Release (); + } + pShellLinkA->Release (); + CoUninitialize (); + return hr; +} + +HRESULT CreateShortcutWithAppIdW (LPCWSTR pszShortcutPath, LPCWSTR pszTargetPath, LPCWSTR pszAppId) +{ + HRESULT hr; + hr = CoInitialize (NULL); + if (FAILED (hr)) + { + return hr; + } + IShellLinkW* pShellLinkW = NULL; + hr = CoCreateInstance (CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, (void**)&pShellLinkW); + if (FAILED (hr)) + { + CoUninitialize (); + return hr; + } + hr = pShellLinkW->SetPath (pszTargetPath); + if (FAILED (hr)) + { + pShellLinkW->Release (); + CoUninitialize (); + return hr; + } + IPropertyStore* pPropStore = NULL; + hr = pShellLinkW->QueryInterface (IID_IPropertyStore, (void**)&pPropStore); + if (SUCCEEDED (hr)) + { + PROPVARIANT propvar; + hr = InitPropVariantFromString (pszAppId, &propvar); + if (SUCCEEDED (hr)) + { + hr = pPropStore->SetValue (PKEY_AppUserModel_ID, propvar); + if (SUCCEEDED (hr)) + { + hr = pPropStore->Commit (); + } + PropVariantClear (&propvar); + } + pPropStore->Release (); + } + IPersistFile* pPersistFile = NULL; + hr = pShellLinkW->QueryInterface (IID_IPersistFile, (void**)&pPersistFile); + if (SUCCEEDED (hr)) + { + hr = pPersistFile->Save (pszShortcutPath, TRUE); + pPersistFile->Release (); + } + pShellLinkW->Release (); + CoUninitialize (); + return hr; +} \ No newline at end of file diff --git a/ToastNotification/ToastNotification.h b/ToastNotification/ToastNotification.h new file mode 100644 index 0000000..0021e69 --- /dev/null +++ b/ToastNotification/ToastNotification.h @@ -0,0 +1,17 @@ +#pragma once +#ifdef TOASTNOTICE_EXPORTS +#define TOASTNOTICE_API __declspec(dllexport) +#else +#define TOASTNOTICE_API __declspec(dllimport) +#endif + +#include + +typedef void (*_NOTICE_PRESS_CALLBACK) (void); +typedef _NOTICE_PRESS_CALLBACK NOTICE_PRESS_CALLBACK; +// ʹ COM IStream * +typedef HANDLE HISTREAM; + +extern "C" TOASTNOTICE_API bool CreateToastNotification (LPCWSTR identityName, LPCWSTR title, LPCWSTR text, NOTICE_PRESS_CALLBACK callback, HISTREAM imgFile); +extern "C" TOASTNOTICE_API HRESULT CreateShortcutWithAppIdA (LPCSTR pszShortcutPath, LPCSTR pszTargetPath, LPCSTR pszAppId); +extern "C" TOASTNOTICE_API HRESULT CreateShortcutWithAppIdW (LPCWSTR pszShortcutPath, LPCWSTR pszTargetPath, LPCWSTR pszAppId); \ No newline at end of file diff --git a/ToastNotification/ToastNotification.sln b/ToastNotification/ToastNotification.sln new file mode 100644 index 0000000..264e1a6 --- /dev/null +++ b/ToastNotification/ToastNotification.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 12 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ToastNotification", "ToastNotification.vcxproj", "{59131AB7-2A7D-9A09-8223-174C3F5E0F57}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {59131AB7-2A7D-9A09-8223-174C3F5E0F57}.Debug|Win32.ActiveCfg = Debug|Win32 + {59131AB7-2A7D-9A09-8223-174C3F5E0F57}.Debug|Win32.Build.0 = Debug|Win32 + {59131AB7-2A7D-9A09-8223-174C3F5E0F57}.Release|Win32.ActiveCfg = Release|Win32 + {59131AB7-2A7D-9A09-8223-174C3F5E0F57}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/ToastNotification/ToastNotification.vcxproj b/ToastNotification/ToastNotification.vcxproj new file mode 100644 index 0000000..7786d2c --- /dev/null +++ b/ToastNotification/ToastNotification.vcxproj @@ -0,0 +1,170 @@ + + + + + Debug + ARM + + + Debug + Win32 + + + Release + ARM + + + Release + Win32 + + + + $(VCTargetsPath11) + 12.0 + + + Win32Proj + {E10C6272-B876-4DC6-9E13-7CA646863B50} + ToastNotification + + + + DynamicLibrary + true + v120 + Unicode + + + DynamicLibrary + true + v120 + Unicode + + + DynamicLibrary + false + v120 + Unicode + + + DynamicLibrary + false + v120 + Unicode + + + + + + + + + + + + + + + + + + + false + $(VCINSTALLDIR)\vcpackages;$(VCInstallDir)atlmfc\lib;$(VCInstallDir)lib;$(WindowsSdkDir)\References\CommonConfiguration\Neutral + + + false + $(VCINSTALLDIR)\vcpackages;$(VCInstallDir)atlmfc\lib;$(VCInstallDir)lib;$(WindowsSdkDir)\References\CommonConfiguration\Neutral + + + false + $(VCINSTALLDIR)\vcpackages;$(VCInstallDir)atlmfc\lib;$(VCInstallDir)lib;$(WindowsSdkDir)\References\CommonConfiguration\Neutral + + + false + $(VCINSTALLDIR)\vcpackages;$(VCInstallDir)atlmfc\lib;$(VCInstallDir)lib;$(WindowsSdkDir)\References\CommonConfiguration\Neutral + + + + WIN32;_DEBUG;TOASTNOTICE_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + Level3 + ProgramDatabase + Disabled + true + false + /ZW:nostdlib /FUplatform.winmd /FUwindows.winmd %(AdditionalOptions) + Create + + + MachineX86 + true + NotSet + shlwapi.lib;%(AdditionalDependencies) + + + + + WIN32;_DEBUG;TOASTNOTICE_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + Level3 + ProgramDatabase + Disabled + true + false + /ZW:nostdlib /FUplatform.winmd /FUwindows.winmd %(AdditionalOptions) + Create + + + true + NotSet + + + + + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + Level3 + ProgramDatabase + true + /ZW:nostdlib /FUplatform.winmd /FUWindows.winmd %(AdditionalOptions) + + + MachineX86 + true + Console + true + true + shlwapi.lib;%(AdditionalDependencies) + + + + + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + Level3 + ProgramDatabase + true + /ZW:nostdlib /FUplatform.winmd /FUWindows.winmd %(AdditionalOptions) + + + true + Console + true + true + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ToastNotification/stdafx.h b/ToastNotification/stdafx.h new file mode 100644 index 0000000..efb81d4 --- /dev/null +++ b/ToastNotification/stdafx.h @@ -0,0 +1,23 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +using namespace Microsoft::WRL; +using namespace ABI::Windows::UI::Notifications; +using namespace ABI::Windows::Data::Xml::Dom; +using namespace Microsoft::WRL::Wrappers;