diff --git a/AppInstaller.sln b/AppInstaller.sln index 39e9805..3e34535 100644 --- a/AppInstaller.sln +++ b/AppInstaller.sln @@ -20,6 +20,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PriReader2", "PriReader2\Pr EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CertificateManager", "CertificateManager\CertificateManager.vcxproj", "{22702832-C3FD-48E5-BC7D-3879CA50A2ED}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AppInstallerConsole", "AppInstallerConsole\AppInstallerConsole.vcxproj", "{D1338693-D56A-45D4-9BA6-DDA67F9E0AB3}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -172,6 +174,24 @@ Global {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 + {D1338693-D56A-45D4-9BA6-DDA67F9E0AB3}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {D1338693-D56A-45D4-9BA6-DDA67F9E0AB3}.Debug|Any CPU.Build.0 = Debug|Win32 + {D1338693-D56A-45D4-9BA6-DDA67F9E0AB3}.Debug|ARM.ActiveCfg = Debug|Win32 + {D1338693-D56A-45D4-9BA6-DDA67F9E0AB3}.Debug|Win32.ActiveCfg = Debug|Win32 + {D1338693-D56A-45D4-9BA6-DDA67F9E0AB3}.Debug|Win32.Build.0 = Debug|Win32 + {D1338693-D56A-45D4-9BA6-DDA67F9E0AB3}.Debug|x64.ActiveCfg = Debug|x64 + {D1338693-D56A-45D4-9BA6-DDA67F9E0AB3}.Debug|x64.Build.0 = Debug|x64 + {D1338693-D56A-45D4-9BA6-DDA67F9E0AB3}.Debug|x86.ActiveCfg = Debug|Win32 + {D1338693-D56A-45D4-9BA6-DDA67F9E0AB3}.Debug|x86.Build.0 = Debug|Win32 + {D1338693-D56A-45D4-9BA6-DDA67F9E0AB3}.Release|Any CPU.ActiveCfg = Release|Win32 + {D1338693-D56A-45D4-9BA6-DDA67F9E0AB3}.Release|Any CPU.Build.0 = Release|Win32 + {D1338693-D56A-45D4-9BA6-DDA67F9E0AB3}.Release|ARM.ActiveCfg = Release|Win32 + {D1338693-D56A-45D4-9BA6-DDA67F9E0AB3}.Release|Win32.ActiveCfg = Release|Win32 + {D1338693-D56A-45D4-9BA6-DDA67F9E0AB3}.Release|Win32.Build.0 = Release|Win32 + {D1338693-D56A-45D4-9BA6-DDA67F9E0AB3}.Release|x64.ActiveCfg = Release|x64 + {D1338693-D56A-45D4-9BA6-DDA67F9E0AB3}.Release|x64.Build.0 = Release|x64 + {D1338693-D56A-45D4-9BA6-DDA67F9E0AB3}.Release|x86.ActiveCfg = Release|Win32 + {D1338693-D56A-45D4-9BA6-DDA67F9E0AB3}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/AppInstaller/pkgcode.h b/AppInstaller/pkgcode.h index 94ea728..8393ab8 100644 --- a/AppInstaller/pkgcode.h +++ b/AppInstaller/pkgcode.h @@ -571,7 +571,7 @@ bool AppxReader::isFileReaderAvailable () bool AppxReader::destroy () { if (!this->isAvailable ()) return false; // 表示已销毁等 - this->m_appxReader->Release (); + if (this->m_appxReader) this->m_appxReader->Release (); this->m_appxReader = NULL; this->m_filePath = std::wstring (L""); return true; @@ -1145,7 +1145,7 @@ bool BundleReader::isFileReaderAvailable () bool BundleReader::destroy () { if (!this->isAvailable ()) return false; // 表示已销毁等 - this->m_bundleReader->Release (); + if (this->m_bundleReader) this->m_bundleReader->Release (); this->m_bundleReader = NULL; this->m_filePath = std::wstring (L""); return true; diff --git a/AppInstallerConsole/AppInstaller.rc b/AppInstallerConsole/AppInstaller.rc new file mode 100644 index 0000000..46fe03a --- /dev/null +++ b/AppInstallerConsole/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 "允许应用程序在进入后台后继续执行一段时间的操作" + 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/AppInstallerConsole/AppInstaller.vcxproj b/AppInstallerConsole/AppInstaller.vcxproj new file mode 100644 index 0000000..dbae118 --- /dev/null +++ b/AppInstallerConsole/AppInstaller.vcxproj @@ -0,0 +1,335 @@ +锘 + + + + Debug + ARM + + + Debug + Win32 + + + Release + ARM + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {D417C165-3F17-40C4-8C7B-0F5AACEF62C5} + Win32Proj + AppInstaller + AppInstallerConsole + 8.1 + + + + Application + true + v140 + Unicode + false + false + + + Application + true + v140 + Unicode + true + false + + + Application + false + v140 + true + Unicode + false + + + 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/AppInstallerConsole/AppInstaller.vcxproj.filters b/AppInstallerConsole/AppInstaller.vcxproj.filters new file mode 100644 index 0000000..e075e93 --- /dev/null +++ b/AppInstallerConsole/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/AppInstallerConsole/AppInstallerConsole.vcxproj b/AppInstallerConsole/AppInstallerConsole.vcxproj new file mode 100644 index 0000000..78008a0 --- /dev/null +++ b/AppInstallerConsole/AppInstallerConsole.vcxproj @@ -0,0 +1,171 @@ +锘 + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {D1338693-D56A-45D4-9BA6-DDA67F9E0AB3} + Win32Proj + AppInstallerConsole + 8.1 + + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstaller\AppLauncher;E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstaller\Base64Img;E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstaller\CertificateManager;E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstaller\PackageManagerAdd;E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstaller\PriReader2;E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstaller\ShoutcutCreater;E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstaller\ToastNotification;$(IncludePath) + + + true + + + false + E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstaller\AppLauncher;E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstaller\Base64Img;E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstaller\CertificateManager;E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstaller\PackageManagerAdd;E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstaller\PriReader2;E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstaller\ShoutcutCreater;E:\Profiles\Bruce\Documents\Visual Studio 2015\Projects\AppInstaller\ToastNotification;$(IncludePath) + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + 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;%(AdditionalDependencies) + + + + + + + Level3 + Disabled + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + 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;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/AppInstallerConsole/AppInstallerConsole.vcxproj.filters b/AppInstallerConsole/AppInstallerConsole.vcxproj.filters new file mode 100644 index 0000000..9e7106d --- /dev/null +++ b/AppInstallerConsole/AppInstallerConsole.vcxproj.filters @@ -0,0 +1,53 @@ +锘 + + + + {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/AppInstallerConsole/base64logo.h b/AppInstallerConsole/base64logo.h new file mode 100644 index 0000000..7457968 --- /dev/null +++ b/AppInstallerConsole/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/AppInstallerConsole/initread.h b/AppInstallerConsole/initread.h new file mode 100644 index 0000000..da43915 --- /dev/null +++ b/AppInstallerConsole/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/AppInstallerConsole/localeex.h b/AppInstallerConsole/localeex.h new file mode 100644 index 0000000..326b816 --- /dev/null +++ b/AppInstallerConsole/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/AppInstallerConsole/main.cpp b/AppInstallerConsole/main.cpp new file mode 100644 index 0000000..98b802a --- /dev/null +++ b/AppInstallerConsole/main.cpp @@ -0,0 +1,569 @@ +#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 "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 +#include + +using namespace std; + +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_cpp +#define rcIcon(resID) LoadRCIcon (resID) + +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); +} + +std::wstring StrPrintFormatW (LPCWSTR format, ...) +{ + va_list args; + va_start (args, format); + size_t sizeBuf = 256; + WCHAR *buffer = (WCHAR *)malloc (sizeBuf * sizeof (WCHAR)); + 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; +} + +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 g_pkgPath = L""; +pkgreader g_reader; +LPCWSTR g_idenName = L"Microsoft.DesktopAppInstaller"; +PackageInfomation g_pkgInfo; + +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; +} + +typedef struct _CMDARGUMENT +{ + std::vector front; + std::vector body; + std::vector rear; + int flag; +} CMDARGUMENT; + +std::vector cmdargs = +{ + {{L"", L"/", L"-"}, {L"HELP", L"?", L"H"}, {}, 5}, +}; + +// 编号为大于 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)); } + +void TaskInstallPackage (); +void TaskInstallPackages (size_t serial, size_t total); +void PrintHelpText () +{ + wchar_t path [MAX_PATH] = {0}; + GetModuleFileNameW (NULL, path, MAX_PATH); + std::wcout << "Usage: " << endl; + std::wcout << L'\t' << PathFindFileNameW (path) << L" " << endl; + std::wcout << L"\t\t" << "Install packages." << endl; + std::wcout << L'\t' << PathFindFileNameW (path) << L" /?" << endl; + std::wcout << L"\t\t" << "Show help." << endl; +} +void middle (wstring s) +{ + HANDLE hOutput = GetStdHandle (STD_OUTPUT_HANDLE); + CONSOLE_SCREEN_BUFFER_INFO bInfo; + GetConsoleScreenBufferInfo (hOutput, &bInfo); + int len = bInfo.dwSize.X / 2 - s.size () / 2; + wprintf (L"\033[%dC", len); + wcout << s; +} + +// 返回真时代表执行 GUI 进程 +bool ReadCommand (int argc, LPWSTR *argv) +{ + std::vector vecObjSwFiles; + bool bDisplayHelp = false; + for (size_t cnt = 1; cnt < (size_t)argc; cnt ++) + { + int res = GetCmdArgSerial (argv [cnt]); + if (res > 0) + { + switch (res) + { + case 5: bDisplayHelp = true; break; + } + } + else + { + if (IsFileExistsW (argv [cnt])) push_no_repeat (vecObjSwFiles, argv [cnt]); + } + } + if (bDisplayHelp) // 处理命令参数提示 + { + PrintHelpText (); + return false; + } + if (vecObjSwFiles.size () == 1) + { + g_pkgPath = vecObjSwFiles [0]; + return true; + } + else if (vecObjSwFiles.size () <= 0) + { + wchar_t path [MAX_PATH] = {0}; + if (GetModuleFileNameW (NULL, path, MAX_PATH)) + { + std::wstring cmdline = L"\"" + std::wstring (path) + L"\" /?"; + 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 (vecObjSwFiles.size () > 1) // 面对多个文件 + { + wchar_t path [MAX_PATH] = {0}; + if (GetModuleFileNameW (NULL, path, MAX_PATH)) + { + for (size_t cnt = 0; cnt < vecObjSwFiles.size (); cnt ++) + { + g_pkgPath = vecObjSwFiles [cnt]; + wstringstream ss; + ss << (cnt + 1) << L" of " << vecObjSwFiles.size () << endl; + middle (ss.str ().c_str ()); + std::wstring cmdline = L"\"" + std::wstring (path) + L"\" \"" + g_pkgPath + L'\"'; + 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; +} + +// 返回真时代表执行 GUI 进程 +bool ReadCommand (LPWSTR lpCmdLine) +{ + int iArgc = 0; + LPWSTR *lpArgv = CommandLineToArgvW (lpCmdLine, &iArgc); + return ReadCommand (iArgc, lpArgv); +} + +void ProgressCallback (unsigned uPrecent) +{ + wcout << L'\r'; + wcout << StrPrintFormatW (GetRCString_cpp (PAGE_2_INSTALLING).c_str (), (int)uPrecent); +} + +void TaskInstallPackage () +{ + if (g_reader.create (g_pkgPath)) + { + wcout << GetRCString_cpp (PAGE_LOADING); + g_pkgInfo.create (g_reader); + wcout << L"\r"; + wcout << L"Package File: " << g_pkgPath << endl; + wcout << L'\t' << L"Identity" << endl; + wcout << L"\t\t" << L"Name: " << g_pkgInfo.getIdentityName () << endl; + wcout << L"\t\t" << L"Publisher: " << g_pkgInfo.getIdentityPublisher () << endl; + wcout << L"\t\t" << L"Version: " << g_pkgInfo.getIdentityVersion ().toStringW () << endl; + std::vector archs; + wcout << L"\t\t" << L"Processor Architecture (" << g_pkgInfo.getIdentityProcessorArchitecture (archs) << ") "; + if (archs.size () > 0) + { + std::wstring temp; + for (size_t cnt = 0; cnt < archs.size (); cnt ++) + { + switch (archs [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)archs [cnt] == 12) temp += L"Arm64"; + } + if (cnt + 1 != archs.size ()) temp += L", "; + } + wcout << temp; + } + wcout << endl; + wcout << L'\t' << L"Properties" << endl; + wcout << L"\t\t" << L"Name: " << g_pkgInfo.getPropertyName () << endl; + wcout << L"\t\t" << L"Publisher: " << g_pkgInfo.getPropertyPublisher () << endl; + { + std::wstring &temp = g_pkgInfo.getPropertyDescription (); + if (temp.size () > 0) + { + wcout << L"\t\t" << L"Description: " << temp << endl; + } + } + { + std::vector langs; + g_pkgInfo.getResourceLanguages (langs); + if (langs.size () > 0) + { + wcout << L"\t" << L"Resources" << endl; + wcout << L"\t\t" << L"Languages (" << langs.size () << "): "; + for (size_t cnt = 0; cnt < langs.size (); cnt ++) + { + wcout << langs [cnt]; + if (cnt + 1 != langs.size ()) wcout << L", "; + } + wcout << endl; + } + } + std::vector apps; + g_pkgInfo.getApplications (apps); + wcout << L'\t' << L"Applications (" << apps.size () << ")" << endl; + if (apps.size () > 0) + { + for (auto it : apps) + { + wcout << L"\t\t" << L"Application" << endl; + wcout << L"\t\t\t" << L"App Model User ID: " << it.getAppUserModelID () << endl; + wcout << L"\t\t\t" << L"ID: " << it [L"Id"] << endl; + } + } + std::vector caps; + g_pkgInfo.getCapabilities (caps); + wcout << L'\t' << L"Capabilities (" << caps.size () << ")" << endl; + if (caps.size () > 0) + { + for (auto it : caps) + { + wcout << L"\t\t" << GetRCString_cpp (CapabilitiesNameToID (it)) << endl; + } + } + std::vector deps; + wcout << L'\t' << L"Dependencies (" << deps.size () << ")" << endl; + for (auto it : deps) + { + wcout << L"\t\t" << L"Dependency" << endl; + wcout << L"\t\t\t" << L"Name: " << it.name << endl; + wcout << L"\t\t\t" << L"Publisher: " << it.publisher << endl; + wcout << L"\t\t\t" << L"Version: " << it.versionMin.toStringW () << endl; + } + wcout << StrPrintFormatW (GetRCString_cpp (PAGE_2_TITLE).c_str (), g_pkgInfo.getPropertyName ().c_str ()) << endl; + wcout << GetRCString_cpp (PAGE_2_LOADCERT); + if (LoadCertFromSignedFile (g_pkgPath.c_str ())) wcout << L"Succeeded! " << endl; + else wcout << "Failed. " << endl; + wcout << GetRCString_cpp (PAGE_2_INSTALL); + InstallStatus ires = AddPackageFromPath (g_pkgPath.c_str (), &ProgressCallback); + wcout << endl; + if (ires == InstallStatus::Success) + { + wcout << "Install Succeeded! " << endl; + } + else + { + wcout << "\rInstall Failed. Message: " << GetLastErrorDetailText () << endl; + } + } + else + { + wcout << "\rInstall Failed. Message: Unavailable Package." << endl; + } +} + +void TaskInstallPackages (size_t serial, size_t total) +{ + wcout << serial << L" of " << total << endl; + wcout << L'\t' << GetRCString_cpp (PAGE_LOADING); + g_reader.destroy (); + if (g_reader.create (g_pkgPath)) + { + g_pkgInfo.create (g_reader); + wcout << L"\r"; + wcout << L"\tPackage File: " << g_pkgPath << endl; + wcout << L"\t\t" << L"Identity" << endl; + wcout << L"\t\t\t" << L"Name: " << g_pkgInfo.getIdentityName () << endl; + wcout << L"\t\t\t" << L"Publisher: " << g_pkgInfo.getIdentityPublisher () << endl; + wcout << L"\t\t\t" << L"Version: " << g_pkgInfo.getIdentityVersion ().toStringW () << endl; + std::vector archs; + wcout << L"\t\t\t" << L"Processor Architecture (" << g_pkgInfo.getIdentityProcessorArchitecture (archs) << ") "; + if (archs.size () > 0) + { + std::wstring temp; + for (size_t cnt = 0; cnt < archs.size (); cnt ++) + { + switch (archs [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)archs [cnt] == 12) temp += L"Arm64"; + } + if (cnt + 1 != archs.size ()) temp += L", "; + } + wcout << temp; + } + wcout << endl; + wcout << L"\t\t" << L"Properties" << endl; + wcout << L"\t\t\t" << L"Name: " << g_pkgInfo.getPropertyName () << endl; + wcout << L"\t\t\t" << L"Publisher: " << g_pkgInfo.getPropertyPublisher () << endl; + { + std::wstring &temp = g_pkgInfo.getPropertyDescription (); + if (temp.size () > 0) + { + wcout << L"\t\t\t" << L"Description: " << temp << endl; + } + } + std::vector apps; + g_pkgInfo.getApplications (apps); + wcout << L"\t" << L"Applications (" << apps.size () << ")" << endl; + if (apps.size () > 0) + { + for (auto it : apps) + { + wcout << L"\t\t\t" << L"Application" << endl; + wcout << L"\t\t\t\t" << L"App Model User ID: " << it.getAppUserModelID () << endl; + } + } + wcout << StrPrintFormatW (GetRCString_cpp (PAGE_2_TITLE).c_str (), g_pkgInfo.getPropertyName ().c_str ()) << endl; + wcout << GetRCString_cpp (PAGE_2_LOADCERT); + if (LoadCertFromSignedFile (g_pkgPath.c_str ())) wcout << L"\tSucceeded! " << endl; + else wcout << "\tFailed. " << endl; + wcout << GetRCString_cpp (PAGE_2_INSTALL); + InstallStatus ires = AddPackageFromPath (g_pkgPath.c_str (), &ProgressCallback); + wcout << endl; + if (ires == InstallStatus::Success) + { + wcout << "\tInstall Succeeded! " << endl; + } + else + { + wcout << "\tInstall Failed. Message: " << GetLastErrorDetailText () << endl; + } + } + else + { + wcout << "\r\tInstall Failed. Message: Unavailable Package." << endl; + } +} + +int wmain (int argc, LPWSTR *argv) +{ + + if (argc <= 1) + { + PrintHelpText (); + return 0; + } + setlocale (LC_ALL, ""); + std::wcout.imbue (std::locale ("", LC_CTYPE)); + SetCurrentProcessExplicitAppUserModelID (g_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 ()); + } + CoInitializeEx (NULL, COINIT_MULTITHREADED); + if (ReadCommand (argc, argv)) + { + TaskInstallPackage (); + } + g_reader.destroy (); + return 0; +} \ No newline at end of file diff --git a/AppInstallerConsole/pkgcode.h b/AppInstallerConsole/pkgcode.h new file mode 100644 index 0000000..8393ab8 --- /dev/null +++ b/AppInstallerConsole/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); + // 注意:当执行销毁操作时导入的读取器也会销毁!此方法是很危险的操作 + 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; // 表示已销毁等 + if (this->m_appxReader) 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); + // 注意:当执行销毁操作时导入的读取器也会销毁!此方法是很危险的操作 + 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; // 表示已销毁等 + if (this->m_bundleReader) 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/AppInstallerConsole/pkginfo.h b/AppInstallerConsole/pkginfo.h new file mode 100644 index 0000000..158b750 --- /dev/null +++ b/AppInstallerConsole/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/AppInstallerConsole/priread.h b/AppInstallerConsole/priread.h new file mode 100644 index 0000000..0041052 --- /dev/null +++ b/AppInstallerConsole/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/AppInstallerConsole/res/Button/Large/blank.png b/AppInstallerConsole/res/Button/Large/blank.png new file mode 100644 index 0000000..4a12390 Binary files /dev/null and b/AppInstallerConsole/res/Button/Large/blank.png differ diff --git a/AppInstallerConsole/res/Button/Large/blank_light.png b/AppInstallerConsole/res/Button/Large/blank_light.png new file mode 100644 index 0000000..a44303d Binary files /dev/null and b/AppInstallerConsole/res/Button/Large/blank_light.png differ diff --git a/AppInstallerConsole/res/Button/Large/blank_press.png b/AppInstallerConsole/res/Button/Large/blank_press.png new file mode 100644 index 0000000..0376f98 Binary files /dev/null and b/AppInstallerConsole/res/Button/Large/blank_press.png differ diff --git a/AppInstallerConsole/res/Button/Large/cancel_window_light.png b/AppInstallerConsole/res/Button/Large/cancel_window_light.png new file mode 100644 index 0000000..45e3fe0 Binary files /dev/null and b/AppInstallerConsole/res/Button/Large/cancel_window_light.png differ diff --git a/AppInstallerConsole/res/Button/Large/cancel_window_normal.png b/AppInstallerConsole/res/Button/Large/cancel_window_normal.png new file mode 100644 index 0000000..dd1442c Binary files /dev/null and b/AppInstallerConsole/res/Button/Large/cancel_window_normal.png differ diff --git a/AppInstallerConsole/res/Button/Large/cancel_window_press.png b/AppInstallerConsole/res/Button/Large/cancel_window_press.png new file mode 100644 index 0000000..171508c Binary files /dev/null and b/AppInstallerConsole/res/Button/Large/cancel_window_press.png differ diff --git a/AppInstallerConsole/res/Button/Large/max_light.png b/AppInstallerConsole/res/Button/Large/max_light.png new file mode 100644 index 0000000..8b6fe0c Binary files /dev/null and b/AppInstallerConsole/res/Button/Large/max_light.png differ diff --git a/AppInstallerConsole/res/Button/Large/max_normal.png b/AppInstallerConsole/res/Button/Large/max_normal.png new file mode 100644 index 0000000..4fcdd76 Binary files /dev/null and b/AppInstallerConsole/res/Button/Large/max_normal.png differ diff --git a/AppInstallerConsole/res/Button/Large/max_press.png b/AppInstallerConsole/res/Button/Large/max_press.png new file mode 100644 index 0000000..53b911a Binary files /dev/null and b/AppInstallerConsole/res/Button/Large/max_press.png differ diff --git a/AppInstallerConsole/res/Button/Large/max_trans_normal.png b/AppInstallerConsole/res/Button/Large/max_trans_normal.png new file mode 100644 index 0000000..09aa968 Binary files /dev/null and b/AppInstallerConsole/res/Button/Large/max_trans_normal.png differ diff --git a/AppInstallerConsole/res/Button/Large/min_light.png b/AppInstallerConsole/res/Button/Large/min_light.png new file mode 100644 index 0000000..8e9e960 Binary files /dev/null and b/AppInstallerConsole/res/Button/Large/min_light.png differ diff --git a/AppInstallerConsole/res/Button/Large/min_normal.png b/AppInstallerConsole/res/Button/Large/min_normal.png new file mode 100644 index 0000000..efe7ffc Binary files /dev/null and b/AppInstallerConsole/res/Button/Large/min_normal.png differ diff --git a/AppInstallerConsole/res/Button/Large/min_press.png b/AppInstallerConsole/res/Button/Large/min_press.png new file mode 100644 index 0000000..c367ae7 Binary files /dev/null and b/AppInstallerConsole/res/Button/Large/min_press.png differ diff --git a/AppInstallerConsole/res/Button/Large/min_trans_normal.png b/AppInstallerConsole/res/Button/Large/min_trans_normal.png new file mode 100644 index 0000000..8e9a54f Binary files /dev/null and b/AppInstallerConsole/res/Button/Large/min_trans_normal.png differ diff --git a/AppInstallerConsole/res/Button/Large/restore_light.png b/AppInstallerConsole/res/Button/Large/restore_light.png new file mode 100644 index 0000000..3552d68 Binary files /dev/null and b/AppInstallerConsole/res/Button/Large/restore_light.png differ diff --git a/AppInstallerConsole/res/Button/Large/restore_normal.png b/AppInstallerConsole/res/Button/Large/restore_normal.png new file mode 100644 index 0000000..8aad4d5 Binary files /dev/null and b/AppInstallerConsole/res/Button/Large/restore_normal.png differ diff --git a/AppInstallerConsole/res/Button/Large/restore_press.png b/AppInstallerConsole/res/Button/Large/restore_press.png new file mode 100644 index 0000000..a848ece Binary files /dev/null and b/AppInstallerConsole/res/Button/Large/restore_press.png differ diff --git a/AppInstallerConsole/res/Button/Large/restore_trans_normal.png b/AppInstallerConsole/res/Button/Large/restore_trans_normal.png new file mode 100644 index 0000000..bc01f58 Binary files /dev/null and b/AppInstallerConsole/res/Button/Large/restore_trans_normal.png differ diff --git a/AppInstallerConsole/res/Button/Normal/blank.png b/AppInstallerConsole/res/Button/Normal/blank.png new file mode 100644 index 0000000..0431c20 Binary files /dev/null and b/AppInstallerConsole/res/Button/Normal/blank.png differ diff --git a/AppInstallerConsole/res/Button/Normal/blank_light.png b/AppInstallerConsole/res/Button/Normal/blank_light.png new file mode 100644 index 0000000..3328fa7 Binary files /dev/null and b/AppInstallerConsole/res/Button/Normal/blank_light.png differ diff --git a/AppInstallerConsole/res/Button/Normal/blank_press.png b/AppInstallerConsole/res/Button/Normal/blank_press.png new file mode 100644 index 0000000..cf8aa85 Binary files /dev/null and b/AppInstallerConsole/res/Button/Normal/blank_press.png differ diff --git a/AppInstallerConsole/res/Button/Normal/cancel_back.png b/AppInstallerConsole/res/Button/Normal/cancel_back.png new file mode 100644 index 0000000..6ed1343 Binary files /dev/null and b/AppInstallerConsole/res/Button/Normal/cancel_back.png differ diff --git a/AppInstallerConsole/res/Button/Normal/cancel_light.png b/AppInstallerConsole/res/Button/Normal/cancel_light.png new file mode 100644 index 0000000..bc89c71 Binary files /dev/null and b/AppInstallerConsole/res/Button/Normal/cancel_light.png differ diff --git a/AppInstallerConsole/res/Button/Normal/cancel_press.png b/AppInstallerConsole/res/Button/Normal/cancel_press.png new file mode 100644 index 0000000..6cc0e3c Binary files /dev/null and b/AppInstallerConsole/res/Button/Normal/cancel_press.png differ diff --git a/AppInstallerConsole/res/Button/Normal/max_back.png b/AppInstallerConsole/res/Button/Normal/max_back.png new file mode 100644 index 0000000..92b54c2 Binary files /dev/null and b/AppInstallerConsole/res/Button/Normal/max_back.png differ diff --git a/AppInstallerConsole/res/Button/Normal/max_light.png b/AppInstallerConsole/res/Button/Normal/max_light.png new file mode 100644 index 0000000..10bb4a6 Binary files /dev/null and b/AppInstallerConsole/res/Button/Normal/max_light.png differ diff --git a/AppInstallerConsole/res/Button/Normal/max_press.png b/AppInstallerConsole/res/Button/Normal/max_press.png new file mode 100644 index 0000000..a83fbfc Binary files /dev/null and b/AppInstallerConsole/res/Button/Normal/max_press.png differ diff --git a/AppInstallerConsole/res/Button/Normal/min_back.png b/AppInstallerConsole/res/Button/Normal/min_back.png new file mode 100644 index 0000000..709a12a Binary files /dev/null and b/AppInstallerConsole/res/Button/Normal/min_back.png differ diff --git a/AppInstallerConsole/res/Button/Normal/min_light.png b/AppInstallerConsole/res/Button/Normal/min_light.png new file mode 100644 index 0000000..17675ea Binary files /dev/null and b/AppInstallerConsole/res/Button/Normal/min_light.png differ diff --git a/AppInstallerConsole/res/Button/Normal/min_press.png b/AppInstallerConsole/res/Button/Normal/min_press.png new file mode 100644 index 0000000..db95770 Binary files /dev/null and b/AppInstallerConsole/res/Button/Normal/min_press.png differ diff --git a/AppInstallerConsole/res/Button/Normal/restore_back.png b/AppInstallerConsole/res/Button/Normal/restore_back.png new file mode 100644 index 0000000..c10da8b Binary files /dev/null and b/AppInstallerConsole/res/Button/Normal/restore_back.png differ diff --git a/AppInstallerConsole/res/Button/Normal/restore_light.png b/AppInstallerConsole/res/Button/Normal/restore_light.png new file mode 100644 index 0000000..3eada01 Binary files /dev/null and b/AppInstallerConsole/res/Button/Normal/restore_light.png differ diff --git a/AppInstallerConsole/res/Button/Normal/restore_press.png b/AppInstallerConsole/res/Button/Normal/restore_press.png new file mode 100644 index 0000000..d64f607 Binary files /dev/null and b/AppInstallerConsole/res/Button/Normal/restore_press.png differ diff --git a/AppInstallerConsole/res/Fonts/IDR_SETUP_FONT.TTF b/AppInstallerConsole/res/Fonts/IDR_SETUP_FONT.TTF new file mode 100644 index 0000000..bc89e9c Binary files /dev/null and b/AppInstallerConsole/res/Fonts/IDR_SETUP_FONT.TTF differ diff --git a/AppInstallerConsole/res/Icons/FileIcon.ico b/AppInstallerConsole/res/Icons/FileIcon.ico new file mode 100644 index 0000000..074eb28 Binary files /dev/null and b/AppInstallerConsole/res/Icons/FileIcon.ico differ diff --git a/AppInstallerConsole/res/Icons/IconColor.ico b/AppInstallerConsole/res/Icons/IconColor.ico new file mode 100644 index 0000000..3db5e1a Binary files /dev/null and b/AppInstallerConsole/res/Icons/IconColor.ico differ diff --git a/AppInstallerConsole/res/Icons/IconTitleBar.ico b/AppInstallerConsole/res/Icons/IconTitleBar.ico new file mode 100644 index 0000000..3b0063a Binary files /dev/null and b/AppInstallerConsole/res/Icons/IconTitleBar.ico differ diff --git a/AppInstallerConsole/res/Icons/IconWhite.ico b/AppInstallerConsole/res/Icons/IconWhite.ico new file mode 100644 index 0000000..12dc50a Binary files /dev/null and b/AppInstallerConsole/res/Icons/IconWhite.ico differ diff --git a/AppInstallerConsole/res/Icons/Main.ico b/AppInstallerConsole/res/Icons/Main.ico new file mode 100644 index 0000000..1ba811e Binary files /dev/null and b/AppInstallerConsole/res/Icons/Main.ico differ diff --git a/AppInstallerConsole/res/Pictures/Trans.png b/AppInstallerConsole/res/Pictures/Trans.png new file mode 100644 index 0000000..076cd28 Binary files /dev/null and b/AppInstallerConsole/res/Pictures/Trans.png differ diff --git a/AppInstallerConsole/res/Pictures/Trans_old.png b/AppInstallerConsole/res/Pictures/Trans_old.png new file mode 100644 index 0000000..6e3f92d Binary files /dev/null and b/AppInstallerConsole/res/Pictures/Trans_old.png differ diff --git a/AppInstallerConsole/res/icon.ico b/AppInstallerConsole/res/icon.ico new file mode 100644 index 0000000..f1e0de9 Binary files /dev/null and b/AppInstallerConsole/res/icon.ico differ diff --git a/AppInstallerConsole/res/manifest.xml b/AppInstallerConsole/res/manifest.xml new file mode 100644 index 0000000..44d54ca --- /dev/null +++ b/AppInstallerConsole/res/manifest.xml @@ -0,0 +1,25 @@ + + + + + + + True/PM + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/AppInstallerConsole/res2.h b/AppInstallerConsole/res2.h new file mode 100644 index 0000000..08b8476 --- /dev/null +++ b/AppInstallerConsole/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/AppInstallerConsole/resource.h b/AppInstallerConsole/resource.h new file mode 100644 index 0000000..d1272f2 --- /dev/null +++ b/AppInstallerConsole/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