diff --git a/.gitignore b/.gitignore
index a5d95d6..adf6318 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,4 @@
.vs/
ghost_installer.vcxproj.user
src/resource/ghost_installer.aps
+src/resource/RC*
diff --git a/builds/auto_upx.bat b/builds/auto_upx.bat
new file mode 100644
index 0000000..d7b9979
--- /dev/null
+++ b/builds/auto_upx.bat
@@ -0,0 +1,4 @@
+cd Release
+upx --ultra-brute --no-align --best --compress-resources=1 ghost_installer.exe
+rename ghost_installer.exe Taromati2_Installer.exe
+cd ..
diff --git a/ghost_installer.sln b/ghost_installer.sln
index d23d664..2d47640 100644
--- a/ghost_installer.sln
+++ b/ghost_installer.sln
@@ -7,18 +7,12 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ghost_installer", "ghost_in
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
- Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {C89F04AF-0793-410D-BA2F-10E7042ACD86}.Debug|x64.ActiveCfg = Debug|x64
- {C89F04AF-0793-410D-BA2F-10E7042ACD86}.Debug|x64.Build.0 = Debug|x64
{C89F04AF-0793-410D-BA2F-10E7042ACD86}.Debug|x86.ActiveCfg = Debug|Win32
{C89F04AF-0793-410D-BA2F-10E7042ACD86}.Debug|x86.Build.0 = Debug|Win32
- {C89F04AF-0793-410D-BA2F-10E7042ACD86}.Release|x64.ActiveCfg = Release|x64
- {C89F04AF-0793-410D-BA2F-10E7042ACD86}.Release|x64.Build.0 = Release|x64
{C89F04AF-0793-410D-BA2F-10E7042ACD86}.Release|x86.ActiveCfg = Release|Win32
{C89F04AF-0793-410D-BA2F-10E7042ACD86}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
diff --git a/ghost_installer.vcxproj b/ghost_installer.vcxproj
index 3756fc1..f586f97 100644
--- a/ghost_installer.vcxproj
+++ b/ghost_installer.vcxproj
@@ -19,9 +19,13 @@
-
-
+
+ /await %(AdditionalOptions)
+ /await %(AdditionalOptions)
+ /await %(AdditionalOptions)
+ /await %(AdditionalOptions)
+
@@ -30,6 +34,9 @@
+
+
+
16.0
Win32Proj
@@ -126,12 +133,13 @@
AnySuitable
Size
true
+ MaxSpeed
Windows
true
true
- true
+ false
false
@@ -163,12 +171,13 @@
AnySuitable
Size
true
+ MaxSpeed
Windows
true
true
- true
+ false
false
diff --git a/ghost_installer.vcxproj.filters b/ghost_installer.vcxproj.filters
index 59d52fd..e071530 100644
--- a/ghost_installer.vcxproj.filters
+++ b/ghost_installer.vcxproj.filters
@@ -17,9 +17,6 @@
源文件
-
- 源文件
-
源文件
@@ -37,4 +34,7 @@
资源文件
+
+
+
\ No newline at end of file
diff --git a/src/_gists.cpp b/src/_gists.cpp
index a00e6e2..933910a 100644
--- a/src/_gists.cpp
+++ b/src/_gists.cpp
@@ -1,2 +1,11 @@
#include "my-gists/ukagaka/SSP_Runner.cpp"
-#include "my-gists/windows/LoadStringFromResource.cpp"
+#include "my-gists/windows/WaitForXObjectWithMessageLoop.cpp"
+#include "my-gists/windows/download_file.cpp"
+#include "my-gists/windows/IsNetworkHasCost.cpp"
+
+const wchar_t* NetAgentName() {
+ return L"ghost_installer";
+}
+const wchar_t* temp_filename_gen_header() {
+ return L"ghi";
+}
diff --git a/src/download_temp_file.cpp b/src/download_temp_file.cpp
deleted file mode 100644
index 8e17997..0000000
--- a/src/download_temp_file.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-#include
-#include
-#include
-#include
-#pragma comment(lib, "WinInet.lib")
-std::wstring download_file(const std::wstring& url, const std::wstring& file) {
- //
- HANDLE hFileHandle = CreateFileW(file.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
- if(hFileHandle==INVALID_HANDLE_VALUE) {
- throw std::runtime_error("CreateFileW failed");
- }
- //download file
- HINTERNET hInternet=InternetOpenW(L"ghost_installer", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
- if(hInternet==NULL) {
- throw std::runtime_error("InternetOpenW failed");
- }
- HINTERNET hFile=InternetOpenUrlW(hInternet, url.c_str(), NULL, 0, INTERNET_FLAG_NO_CACHE_WRITE, 0);
- if(hFile==NULL) {
- InternetCloseHandle(hInternet);
- throw std::runtime_error("InternetOpenUrlW failed");
- }
- DWORD dwBytesRead=0;
- DWORD dwBytesWritten=0;
- unsigned char buffer[1024];
- bool full_download=false;
- while(InternetReadFile(hFile, buffer, 1024, &dwBytesRead)) {
- if(dwBytesRead > 0)
- WriteFile(hFileHandle, buffer, dwBytesRead, &dwBytesWritten, NULL);
- else {
- full_download=true;
- break;
- }
- }
- InternetCloseHandle(hFile);
- InternetCloseHandle(hInternet);
- CloseHandle(hFileHandle);
- if(!full_download) {
- throw std::runtime_error("InternetReadFile failed");
- }
- return file;
-}
-std::wstring download_temp_file(const std::wstring& url, const std::wstring& file_suffix) {
- //get temp path
- static wchar_t temp_path[MAX_PATH + 1]{};
- static bool temp_path_initer = (bool)GetTempPath(MAX_PATH, temp_path);
- //generate a temporary file name
- std::wstring temp_file_name;
- temp_file_name.resize(MAX_PATH);
- GetTempFileNameW(temp_path, L"ghi", 0, temp_file_name.data());
- temp_file_name.resize(wcslen(temp_file_name.data()));
- //append file suffix
- temp_file_name += file_suffix;
- //
- return download_file(url, temp_file_name);
-}
diff --git a/src/ghost_installer.cpp b/src/ghost_installer.cpp
index 12d9976..ff07304 100644
--- a/src/ghost_installer.cpp
+++ b/src/ghost_installer.cpp
@@ -1,20 +1,36 @@
-#include
+#include
#include
-#include
#include "my-gists/ukagaka/SSP_Runner.hpp"
-#include "my-gists/windows/LoadStringFromResource.hpp"
+#include "my-gists/windows/WaitForXObjectWithMessageLoop.hpp"
+#include "my-gists/windows/get_temp_path.hpp"
+#include "my-gists/windows/download_file.hpp"
+#include "my-gists/windows/IsNetworkHasCost.hpp"
#include "resource/resource.h"
#include "ghost_installer.hpp"
-//shlwapi.lib
-#pragma comment(lib, "shlwapi.lib")
+namespace download_speed_up_thread {
+ void download_speed_up_ssp() {
+ try {
+ download_file_to_temp_dir(L"https://github.com/Taromati2/package-factory/releases/latest/download/ssp.exe", L"SSP.exe");
+ }
+ catch(const std::exception& e) {
+ MessageBoxA(NULL, e.what(), "Error", MB_OK);
+ throw;
+ }
+ }
+ void download_speed_up_nar() {
+ try {
+ download_file_to_temp_dir(L"https://github.com/Taromati2/package-factory/releases/latest/download/Taromati2.nar", L"Taromati2.nar");
+ }
+ catch(const std::exception& e) {
+ MessageBoxA(NULL, e.what(), "Error", MB_OK);
+ throw;
+ }
+ }
+} // namespace download_speed_up_thread
-std::wstring download_temp_file(const std::wstring& url, const std::wstring& file_suffix);
-std::wstring get_ghost_url() {
- return LoadStringFromResource(IDR_GHOST_URL);
-}
namespace ssp_install {
std::wstring program_dir;
@@ -29,7 +45,7 @@ bool get_edit_Dia_text_as_path(std::wstring& path, HWND hDlg, WORD IDC) {
(LPARAM)0);
if(pathlen == 0) {
MessageBox(hDlg,
- L"No characters entered.",
+ L"请输入路径",
L"Error",
MB_OK);
return false;
@@ -76,7 +92,7 @@ LRESULT CALLBACK InstallPathSelDlgProc(HWND hDlg, UINT message, WPARAM wParam, L
ZeroMemory(&bi, sizeof(bi));
bi.hwndOwner = hDlg;
bi.pszDisplayName = new wchar_t[MAX_PATH];
- bi.lpszTitle = L"Select installation path";
+ bi.lpszTitle = L"选择SSP安装路径";
bi.ulFlags = BIF_RETURNONLYFSDIRS;
LPITEMIDLIST pidl = SHBrowseForFolder(&bi);
if(pidl != NULL) {
@@ -103,86 +119,123 @@ int APIENTRY WinMain(
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPSTR lpCmdLine,
_In_ int nShowCmd) {
- try {
- SSP_Runner SSP;
- if(SSP.IsInstalled()) {
- install_ghost:
- auto nar_file = download_temp_file(get_ghost_url(), L".nar");
- SSP.install_nar(nar_file);
- //We can't wait for ssp to terminate before deleting the nar file, because when ghost ends is up to the user
- //So, no clearing of temporary files
+ //*
+ if(IsNetworkHasCost()) {
+ auto result = MessageBox(NULL,
+ L"您的网络可能是计费网络,是否继续安装?",
+ L"注意",
+ MB_YESNO);
+ if(result == IDNO)
+ return 0;
+ }
+ //*/
+
+ SSP_Runner SSP;
+ HANDLE nar_download_thread = NULL;
+ auto downloading_ui = CreateDialogW(hInstance, (LPCTSTR)IDD_DOWNLOADING, NULL, NULL);
+ if(SSP.IsInstalled()) {
+ nar_download_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)download_speed_up_thread::download_speed_up_nar, NULL, 0, NULL);
+ install_ghost:
+ if(!nar_download_thread) {
+ MessageBox(NULL,
+ L"创建下载进程失败",
+ L"Error",
+ MB_OK);
+ return 1;
+ }
+ ShowWindow(downloading_ui, SW_SHOW);
+ DWORD wait_result = WaitForSingleObjectWithMessageLoop(nar_download_thread, INFINITE);
+ ShowWindow(downloading_ui, SW_HIDE);
+ if(wait_result == WAIT_FAILED) {
+ MessageBox(NULL, L"下载nar失败", L"Error", MB_OK);
+ exit(1);
}
- else {
+ auto nar_file = std::wstring(get_temp_path()) + L"Taromati2.nar";
+ #ifndef _DEBUG
+ SSP.install_nar(nar_file, L"/o", L"callghost,deletesource");
+ #else
+ SSP.install_nar(nar_file, L"/o", L"callghost");
+ #endif
+ //We can't wait for ssp to terminate before deleting the nar file, because when ghost ends is up to the user
+ //So, no clearing of temporary files
+ }
+ else {
+ auto ssp_download_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)download_speed_up_thread::download_speed_up_ssp, NULL, 0, NULL);
+ if(!ssp_download_thread) {
+ MessageBox(NULL,
+ L"创建下载进程失败",
+ L"Error",
+ MB_OK);
+ return 1;
+ }
+ auto response = MessageBox(NULL,
+ L"SSP未安装,此程序是运行ghost的基础平台\n点击确认以安装SSP并继续\n若已安装SSP,请关掉SSP并在接下来的安装路径选择中选择现有的SSP路径以更新SSP至最新版本",
+ L"SSP未安装",
+ MB_YESNO);
+ if(response != IDYES)
+ return 0;
+ {
+ //wait for ssp to download
+ DWORD wait_result = WaitForSingleObjectWithMessageLoop(ssp_download_thread, 0);
+ if(wait_result == WAIT_OBJECT_0) {
+ //start nar download
+ nar_download_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)download_speed_up_thread::download_speed_up_nar, NULL, 0, NULL);
+ }
+ auto ssp_file = std::wstring(get_temp_path()) + L"SSP.exe";
+ EXE_Runner SSP_EXE(ssp_file);
+ //show install path dialog
+ ssp_install::program_dir = DefaultSSPinstallPath();
+ auto install_path_scl_ui = CreateDialogW(hInstance, (LPCTSTR)IDD_INSTALLATION_PATH_SELECTION, NULL, (DLGPROC)InstallPathSelDlgProc);
+ ShowWindow(install_path_scl_ui, SW_SHOW);
{
- //download and install SSP
- auto ssp_file = download_temp_file(L"http://ssp.shillest.net/archive/redir.cgi?stable&full", L".exe");
- EXE_Runner SSP_EXE(ssp_file);
- //show install path dialog
- ssp_install::program_dir = DefaultSSPinstallPath();
- auto install_path_scl_ui = CreateDialogW(hInstance, (LPCTSTR)IDD_INSTALLATION_PATH_SELECTION, NULL, (DLGPROC)InstallPathSelDlgProc);
- ShowWindow(install_path_scl_ui, SW_SHOW);
- {
- MSG msg;
- while(GetMessage(&msg, NULL, 0, 0)) {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- if(ssp_install::ok_to_install)
- break;
- }
+ MSG msg;
+ while(GetMessage(&msg, NULL, 0, 0)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ if(ssp_install::ok_to_install)
+ break;
}
- DestroyWindow(install_path_scl_ui);
- //create installation directory
- switch(SHCreateDirectoryExW(NULL, ssp_install::program_dir.c_str(), NULL)) {
- case ERROR_ALREADY_EXISTS:
- case ERROR_SUCCESS:
- case ERROR_FILE_EXISTS:
- //install SSP
- SSP_EXE.RunAndWait(L"-o\"" + ssp_install::program_dir + L"\"", L"-y");
- //Delete temporary files
- DeleteFileW(ssp_file.c_str());
- break;
- default:
- //Delete temporary files
- DeleteFileW(ssp_file.c_str());
- MessageBoxW(NULL, L"Could not create installation directory.", L"Error", MB_OK);
+ }
+ DestroyWindow(install_path_scl_ui);
+ //create installation directory
+ switch(SHCreateDirectoryExW(NULL, ssp_install::program_dir.c_str(), NULL)) {
+ case ERROR_ALREADY_EXISTS:
+ case ERROR_SUCCESS:
+ case ERROR_FILE_EXISTS: {
+ //wait for ssp to download
+ ShowWindow(downloading_ui, SW_SHOW);
+ DWORD wait_result = WaitForSingleObjectWithMessageLoop(ssp_download_thread, INFINITE);
+ ShowWindow(downloading_ui, SW_HIDE);
+ if(wait_result != WAIT_OBJECT_0) {
+ MessageBox(NULL, L"SSP下载失败", L"SSP下载失败", MB_OK);
return 1;
}
+ //close the ssp download thread
+ CloseHandle(ssp_download_thread);
+ //start nar download
+ if(!nar_download_thread)
+ nar_download_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)download_speed_up_thread::download_speed_up_nar, NULL, 0, NULL);
+ //install SSP
+ SSP_EXE.RunAndWait(L"-o\"" + ssp_install::program_dir + L"\"", L"-y");
+ break;
+ }
+ default:
+ MessageBoxW(NULL, L"未能创建安装文件夹\n请考虑以管理员运行此程序或检查安装路径", L"Error", MB_OK);
+ return 1;
}
//set SSP_Runner's path
SSP.reset_path(ssp_install::program_dir + L"\\ssp.exe");
- if(!SSP.IsInstalled())
- MessageBoxW(NULL, L"Could not install SSP.", L"Error", MB_OK);
- //delete ghost dir because the Japanese based Emily will plague users of other languages
- //using SHFileOperation
- //Does not delete the balloon folder as ghost may not come with a balloon
- {
- auto ghost_dir = ssp_install::program_dir + L"\\ghost";
- SHFILEOPSTRUCTW op;
- ZeroMemory(&op, sizeof(op));
- op.wFunc = FO_DELETE;
- op.pFrom = ghost_dir.c_str();
- op.fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_NOCONFIRMMKDIR;
- SHFileOperationW(&op);
- }
- //get language id
- auto langid = GetUserDefaultUILanguage();
- //install language pack
- auto langpack_url = L"http://ssp.shillest.net/archive/redir.cgi?stable&langpack=" + std::to_wstring(langid);
- try {
- auto langpack_file = download_temp_file(langpack_url, L".nar");
- SSP.install_nar(langpack_file);
+ if(!SSP.IsInstalled()) {
+ MessageBoxW(NULL, L"未能安装SSP", L"Error", MB_OK);
+ return 1;
}
- catch(...) {
- }
- //install ghost
- goto install_ghost;
+ //Delete temporary files
+ DeleteFileW(ssp_file.c_str());
}
- return 0;
- }
- catch(const std::exception& e) {
- MessageBoxA(NULL, e.what(), "Error", MB_OK);
- return 1;
+ //install ghost
+ goto install_ghost;
}
+ return 0;
}
std::wstring DefaultSSPinstallPath() {
diff --git a/src/ghost_installer.hpp b/src/ghost_installer.hpp
index 7604cb3..f57b94c 100644
--- a/src/ghost_installer.hpp
+++ b/src/ghost_installer.hpp
@@ -1,3 +1,2 @@
#pragma once
-
std::wstring DefaultSSPinstallPath();
diff --git a/src/my-gists b/src/my-gists
index e89fc31..c68d6e7 160000
--- a/src/my-gists
+++ b/src/my-gists
@@ -1 +1 @@
-Subproject commit e89fc31fbf875b7d318fa6169b72811f296933a3
+Subproject commit c68d6e733a81fb777a083d40de69c8012d33a699
diff --git a/src/resource/ghost_installer.rc b/src/resource/ghost_installer.rc
index 8ca292e..c7a3750 100644
--- a/src/resource/ghost_installer.rc
+++ b/src/resource/ghost_installer.rc
@@ -5,35 +5,10 @@
#include "resource.h"
#include "windows.h"
/////////////////////////////////////////////////////////////////////////////
-// 中文(简体,中国) resources
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
-LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
-
-#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
+// 非特定语言 resources
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU)
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
/////////////////////////////////////////////////////////////////////////////
//
@@ -41,8 +16,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 1,0,0,1
- PRODUCTVERSION 1,0,0,1
+ FILEVERSION 1,0,0,0
+ PRODUCTVERSION 1,0,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -57,14 +32,14 @@ BEGIN
BEGIN
BLOCK "000004b0"
BEGIN
- VALUE "CompanyName", "TODO: <公司名>"
- VALUE "FileDescription", "TODO: <文件说明>"
- VALUE "FileVersion", "1.0.0.1"
- VALUE "InternalName", "ghost_installer.rc"
+ VALUE "CompanyName", "E.tek"
+ VALUE "FileDescription", "Taromati2 Installer"
+ VALUE "FileVersion", "1.0.0.0"
+ VALUE "InternalName", "ghost_installer"
VALUE "LegalCopyright", "Copyright (C) 2022"
- VALUE "OriginalFilename", "ghost_installer.rc"
- VALUE "ProductName", "TODO: <产品名>"
- VALUE "ProductVersion", "1.0.0.1"
+ VALUE "OriginalFilename", "ghost_installer.exe"
+ VALUE "ProductName", "Taromati2"
+ VALUE "ProductVersion", "1.0.0.0"
END
END
BLOCK "VarFileInfo"
@@ -90,6 +65,13 @@ BEGIN
EDITTEXT IDC_PATHEDIT,16,18,244,12,ES_AUTOHSCROLL
END
+IDD_DOWNLOADING DIALOGEX 0, 0, 158, 52
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ LTEXT "所需文件下载中",IDC_STATIC,47,22,63,8
+END
+
/////////////////////////////////////////////////////////////////////////////
//
@@ -106,6 +88,14 @@ BEGIN
TOPMARGIN, 4
BOTTOMMARGIN, 53
END
+
+ IDD_DOWNLOADING, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 151
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 45
+ END
END
#endif // APSTUDIO_INVOKED
@@ -120,18 +110,21 @@ BEGIN
0
END
-#endif // 中文(简体,中国) resources
-/////////////////////////////////////////////////////////////////////////////
-
+IDD_DOWNLOADING AFX_DIALOG_LAYOUT
+BEGIN
+ 0
+END
-#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
-// Generated from the TEXTINCLUDE 3 resource.
+// Icon
//
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_ICON ICON "kikka.ico"
+#endif // 非特定语言 resources
/////////////////////////////////////////////////////////////////////////////
-#endif // not APSTUDIO_INVOKED
diff --git a/src/resource/kikka.ico b/src/resource/kikka.ico
new file mode 100644
index 0000000..90cbc57
Binary files /dev/null and b/src/resource/kikka.ico differ
diff --git a/src/resource/resource.h b/src/resource/resource.h
index 5bbaea4..4399b11 100644
--- a/src/resource/resource.h
+++ b/src/resource/resource.h
@@ -4,8 +4,9 @@
//
#define IDSELECT 100
#define IDC_PATHEDIT 101
+#define IDC_STATIC 101
#define IDD_INSTALLATION_PATH_SELECTION 102
-#define IDR_GHOST_URL 72
+#define IDD_DOWNLOADING 103
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED