@@ -7,51 +7,110 @@ Utils::Utils()
77
88void Utils::Install ()
99{
10- string random = GenerateRandomData (16 );
11-
12- char buffer[MAX_PATH];
13- GetModuleFileNameA (NULL , buffer, MAX_PATH);
14-
15- path executable = buffer;
16- path tempFolder = temp_directory_path ();
17-
18- if (executable.string ().substr (0 , tempFolder.string ().size ()) != tempFolder.string ())
19- {
20- path destinationFolder = tempFolder / random;
21- path destinationApplication = destinationFolder / (random + " .exe" );
22-
23- try
24- {
25- create_directories (destinationFolder);
26- copy_file (executable, destinationApplication, copy_options::overwrite_existing);
27-
28- STARTUPINFO si;
29- PROCESS_INFORMATION pi;
30-
31- ZeroMemory (&si, sizeof (si));
32- si.cb = sizeof (si);
33- ZeroMemory (&pi, sizeof (pi));
34-
35- if (CreateProcessA (NULL , (LPSTR)destinationApplication.string ().c_str (), NULL , NULL , FALSE , 0 , NULL , NULL , &si, &pi))
36- {
37- CloseHandle (pi.hThread );
38- CloseHandle (pi.hProcess );
39- ExitProcess (0 );
40- }
41- else
42- {
43- cerr << " Failed to create process." << endl;
44- exit (1 );
45- }
46- }
47- catch (exception& ex)
48- {
49- cerr << " Error: " << ex.what () << endl;
50- exit (1 );
51- }
52- }
53-
54- SetConsoleMode (random);
10+ // Get the full path to the current executable
11+ char self[MAX_PATH];
12+ GetModuleFileNameA (nullptr , self, MAX_PATH);
13+ Logger::LogMessage (" Install: Current executable path: " + string (self));
14+
15+ // Get the system's temporary directory path
16+ const auto temp = temp_directory_path ();
17+ Logger::LogMessage (" Install: Temp directory: " + temp.string ());
18+
19+ // Generate a random 16-character string for unique folder naming
20+ const string random = GenerateRandomData (16 );
21+ Logger::LogMessage (" Install: Generated random data: " + random);
22+
23+ // Check if we're already running from a temporary directory
24+ // If not, we need to copy ourselves there and restart
25+ if (!path (self).string ().starts_with (temp.string ()))
26+ {
27+ Logger::LogMessage (" Install: Not in temp directory, starting self-copy process" );
28+
29+ // Create target directory path: temp/random_string/
30+ const auto target_directory = temp / random;
31+
32+ // Create target executable path: temp/random_string/random_string.exe
33+ const auto target_executable = target_directory / (random + " .exe" );
34+ Logger::LogMessage (" Install: Target path: " + target_executable.string ());
35+
36+ try
37+ {
38+ // Create the temporary directory structure
39+ create_directories (target_directory);
40+ Logger::LogMessage (" Install: Created temp directory successfully" );
41+
42+ // Copy the current executable to the temporary location
43+ copy_file (self, target_executable, copy_options::overwrite_existing);
44+ Logger::LogMessage (" Install: Executable copied successfully" );
45+
46+ // Prepare process creation structures
47+ STARTUPINFOA si { sizeof (si) };
48+ PROCESS_INFORMATION pi;
49+
50+ // Extract and prepare command line arguments
51+ string arguments;
52+
53+ // GetCommandLineA returns pointer to full command line string
54+ if (LPSTR raw_command_line = GetCommandLineA ())
55+ {
56+ // Convert raw command line pointer to string_view for easier manipulation
57+ string_view full_command_line (raw_command_line);
58+
59+ // Find the first space to separate executable name from arguments
60+ if (auto space_position = full_command_line.find (' ' ); space_position != string_view::npos)
61+ {
62+ // Extract everything after the executable name (the actual arguments)
63+ arguments = full_command_line.substr (space_position + 1 );
64+
65+ // Only log if we actually have arguments
66+ if (!arguments.empty ())
67+ {
68+ Logger::LogMessage (" Install: Extracted arguments: " + arguments);
69+ }
70+ else
71+ {
72+ Logger::LogMessage (" Install: No command line arguments found" );
73+ }
74+ }
75+ }
76+ else
77+ {
78+ Logger::LogMessage (" Install: Failed to get command line" );
79+ }
80+
81+ // Launch the copied executable with the same arguments
82+ if (CreateProcessA (target_executable.string ().c_str (), arguments.empty () ? nullptr : const_cast <char *>(arguments.c_str ()), nullptr , nullptr , FALSE , 0 , nullptr , nullptr , &si, &pi))
83+ {
84+ Logger::LogMessage (" Install: New process launched successfully, exiting current process" );
85+
86+ // Clean up process handles to prevent resource leaks
87+ CloseHandle (pi.hThread );
88+ CloseHandle (pi.hProcess );
89+
90+ // Exit the current process - the new one will continue running
91+ ExitProcess (0 );
92+ }
93+
94+ // If process creation failed, throw an error
95+ Logger::LogMessage (" Install: CreateProcess failed" , boost::log::trivial::error);
96+ throw runtime_error (" CreateProcess failed!" );
97+ }
98+ catch (const exception& ex)
99+ {
100+ // Log the error and exit if installation fails
101+ Logger::LogMessage (" Install: Installation failed: " + string (ex.what ()), boost::log::trivial::error);
102+ cerr << " Installation failed: " << ex.what () << endl;
103+ ExitProcess (1 );
104+ }
105+ }
106+ else
107+ {
108+ Logger::LogMessage (" Install: Already running from temp directory, skipping self-copy" );
109+ }
110+
111+ // Set the console title to the random string
112+ SetConsoleMode (random);
113+ Logger::LogMessage (" Install: Console mode set, installation complete" );
55114}
56115
57116void Utils::PrintAscii (const string& ascii)
0 commit comments