Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 66 additions & 9 deletions Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,61 @@
#include <commctrl.h>
#include <shellapi.h>

std::vector<std::string> GetArguments()
struct Arguments
{
std::vector<std::string> syringe_args;
std::string game_args;
};

size_t FindSeparator(const std::wstring& cmdLine)
{
bool inQuotes = false;
size_t len = cmdLine.length();
for (size_t i = 0; i < len; ++i)
{
if (cmdLine[i] == L'\\' && i + 1 < len && cmdLine[i + 1] == L'"')
{
i += 1;
continue;
}

if (cmdLine[i] == L'"')
{
inQuotes = !inQuotes;
continue;
}

if (!inQuotes && cmdLine[i] == L' ')
{
if (i + 3 < len && cmdLine[i + 1] == L'-' && cmdLine[i + 2] == L'-' && cmdLine[i + 3] == L' ')
{
return i;
}
}
}
return std::wstring::npos;
}

Arguments GetArguments()
{
std::wstring wszSyringeArgs;
std::wstring wszGameArgs;
std::wstring lpCmdLine = GetCommandLineW();
auto separator = FindSeparator(lpCmdLine);
if (separator != std::wstring::npos)
{
wszSyringeArgs = lpCmdLine.substr(0, separator);
wszGameArgs = lpCmdLine.substr(separator + 4);
}
else
{
wszSyringeArgs = lpCmdLine;
wszGameArgs = L"";
}

// Get argc, argv in wide chars
int argc = 0;
LPWSTR* argvW = CommandLineToArgvW(GetCommandLineW(), &argc);
LPWSTR* argvW = CommandLineToArgvW(wszSyringeArgs.c_str(), &argc);

// Convert to UTF-8. Skip the first argument as it contains the path to Syringe itself
std::vector<std::string> argv(argc - 1);
Expand All @@ -25,10 +75,17 @@ std::vector<std::string> GetArguments()

LocalFree(argvW);

return argv;
int len = WideCharToMultiByte(CP_UTF8, 0, wszGameArgs.c_str(), -1, nullptr, 0, nullptr, nullptr);
std::string gameArgs = std::string(len - 1, '\0');
WideCharToMultiByte(CP_UTF8, 0, wszGameArgs.c_str(), -1, gameArgs.data(), len, nullptr, nullptr);

return {
argv,
gameArgs,
};
}

int Run(const std::vector<std::string>& arguments)
int Run(const Arguments& arguments)
{
constexpr auto const VersionString = "SyringeEx " SYRINGEEX_VER_TEXT ", based on Syringe 0.7.2.0";

Expand All @@ -39,14 +96,14 @@ int Run(const std::vector<std::string>& arguments)
Log::WriteLine(VersionString);
Log::WriteLine("===============");
Log::WriteLine();
Log::WriteLine("WinMain: arguments = \"%.*s\"", printable(arguments));
Log::WriteLine("WinMain: arguments = \"%.*s\"", printable(arguments.syringe_args));

auto failure = "Could not load executable.";
auto exit_code = ERROR_ERRORS_ENCOUNTERED;

try
{
auto const command = parse_command_line(arguments);
auto const command = parse_command_line(arguments.syringe_args);

Log::WriteLine(
"WinMain: Trying to load executable file \"%.*s\"...",
Expand All @@ -62,10 +119,10 @@ int Run(const std::vector<std::string>& arguments)

Log::WriteLine(
"WinMain: SyringeDebugger::Run(\"%.*s\");",
printable(command.game_arguments));
printable(arguments.game_args));
Log::WriteLine();

Debugger.Run(command.game_arguments);
Debugger.Run(arguments.game_args);
Log::WriteLine("WinMain: SyringeDebugger::Run finished.");
Log::WriteLine("WinMain: Exiting on success.");
return ERROR_SUCCESS;
Expand All @@ -84,7 +141,7 @@ int Run(const std::vector<std::string>& arguments)
{
MessageBoxA(
nullptr, "Syringe cannot be run like that.\n\n"
"Usage:\nSyringe.exe <exe name> [-i=<injectedfile.dll> ...] [--args=\"<arguments>\"]",
"Usage:\nSyringe.exe <exe name> [-i=<injectedfile.dll> ...] [-- <arguments>]",
VersionString, MB_OK | MB_ICONINFORMATION);

Log::WriteLine(
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ syringe.exe game.exe

### Passing Arguments to the Target Executable

Use `--args="..."` to provide arguments for the launched process:
Use `--` as a delimiter to pass arguments to the launched process. All arguments after `--` will be forwarded directly to the target executable:

```
syringe.exe game.exe --args="-CD. -SPAWN"
syringe.exe game.exe -- -CD. -SPAWN
```

### DLL Injection Behavior
Expand Down
22 changes: 9 additions & 13 deletions Support.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,10 @@ inline auto trim(std::string_view string) noexcept

inline auto parse_command_line(const std::vector<std::string>& arguments)
{
static constexpr std::string_view ARGS_FLAG = "--args=";

struct argument_set
{
std::vector<std::string> syringe_arguments;
std::string executable_name;
std::string game_arguments;
};

if (arguments.empty())
Expand All @@ -51,26 +48,25 @@ inline auto parse_command_line(const std::vector<std::string>& arguments)
if (!exe_found && !arg.starts_with("-"))
{
exe_found = true;
ret.executable_name = arg;
continue;
}
if (arg.starts_with('"') && arg.ends_with('"'))
ret.executable_name = arg.substr(1, arg.length() - 2);
else
ret.executable_name = arg;

// game arguments: --args="blob"
if (arg.starts_with(ARGS_FLAG))
{
// extract after --args=
std::string blob = arg.substr(ARGS_FLAG.size());
ret.game_arguments = blob;
continue;
}

// Syringe arguments
ret.syringe_arguments.push_back(arg);
if (arg.starts_with("-i=\"") && arg.ends_with('"'))
ret.syringe_arguments.push_back("-i=" + arg.substr(4, arg.length() - 5));
else
ret.syringe_arguments.push_back(arg);
}

if (!exe_found || ret.executable_name.empty())
throw invalid_command_arguments{};


return ret;
}

Expand Down