@@ -47,6 +47,7 @@ int wmain(int argc, wchar_t* argv[])
4747 std::wstring gameArgs;
4848 std::wstring baseMutexName;
4949 int playerNumber = 1 ;
50+ bool changeWindowName = false ;
5051
5152 if (argc < 2 ) {
5253 print_usage ();
@@ -72,10 +73,11 @@ int wmain(int argc, wchar_t* argv[])
7273 }
7374 }
7475 else if (lower_arg == L" -winclass" ) {
75- injectionInfo.injectionFlags = injectionInfo.injectionFlags | InjectionFlags::HOOK_WND_PROC ;
76+ injectionInfo.injectionFlags = injectionInfo.injectionFlags | InjectionFlags::HOOK_WND_PROC | InjectionFlags:: HOOK_CREATE_WINDOW ;
7677 }
7778 else if (lower_arg == L" -winname" ) {
7879 injectionInfo.injectionFlags = injectionInfo.injectionFlags | InjectionFlags::HOOK_CREATE_WINDOW ;
80+ changeWindowName = true ;
7981 }
8082 else if (lower_arg == L" -mutex" && i + 1 < argc) {
8183 injectionInfo.injectionFlags = injectionInfo.injectionFlags | InjectionFlags::HOOK_CREATE_MUTEX ;
@@ -120,7 +122,7 @@ int wmain(int argc, wchar_t* argv[])
120122 wcscpy_s (injectionInfo.windowClassName , CLASS_NAME_MAX_LENGTH , finalClassName.c_str ());
121123 }
122124
123- if ((injectionInfo. injectionFlags & InjectionFlags:: HOOK_CREATE_WINDOW ) == InjectionFlags:: HOOK_CREATE_WINDOW ) {
125+ if (changeWindowName ) {
124126 std::wstring finalWindowName = L" WinSplitPlus " + std::to_wstring (playerNumber);
125127 wcscpy_s (injectionInfo.windowName , WINDOW_NAME_MAX_LENGTH , finalWindowName.c_str ());
126128 }
@@ -136,30 +138,109 @@ int wmain(int argc, wchar_t* argv[])
136138 wcscpy_s (injectionInfo.mutexNewName , MUTEX_NAME_MAX_LENGTH , finalMutexName.c_str ());
137139 }
138140
139- if (injectionInfo.windowSizeX > 0 || injectionInfo.windowSizeY > 0 || injectionInfo.windowPosX > 0 || injectionInfo.windowPosY > 0 ) {
140- injectionInfo.injectionFlags = injectionInfo.injectionFlags | InjectionFlags::HOOK_SET_WINDOW_POS ;
141+ // Inject the DLL
142+ WCHAR exePath[MAX_PATH ];
143+ GetModuleFileName (NULL , exePath, MAX_PATH );
144+ std::wstring exeDir = exePath;
145+ size_t lastSlash = exeDir.find_last_of (L" \\ /" );
146+ if (lastSlash != std::wstring::npos) {
147+ exeDir = exeDir.substr (0 , lastSlash);
148+ }
149+ std::wstring pluginsDir = exeDir + L" \\ plugins\\ " ;
150+
151+ std::vector<std::wstring> dllsToInject;
152+ std::wstring searchPath = pluginsDir + L" *.dll" ;
153+ WIN32_FIND_DATA wfd;
154+ HANDLE hFind = FindFirstFile (searchPath.c_str (), &wfd);
155+
156+ if (hFind != INVALID_HANDLE_VALUE ) {
157+ do {
158+ std::wstring dllName = wfd.cFileName ;
159+ dllsToInject.push_back (pluginsDir + dllName);
160+ } while (FindNextFile (hFind, &wfd));
161+ FindClose (hFind);
141162 }
142163
143- // Inject the DLL
144- WCHAR dllToInject[] = L" WinSplitPlusIJ.dll" ;
145- DWORD processId = 0 ;
164+ // 3. Check if we found any DLLs
165+ if (dllsToInject.empty ()) {
166+ Sleep (7000 );
167+ std::wcerr << L" Error: No .dll files found in " << pluginsDir << std::endl;
168+ std::wcerr << L" Please ensure a 'plugins' folder exists next to WinSplitPlus.exe and contains your hook DLLs." << std::endl;
169+ // system("pause");
170+ return 1 ;
171+ }
146172
147- std::wcout << L" Launching game: " << gamePath << std::endl;
148- std::wcout << L" Injecting with settings for Player " << playerNumber << L" ..." << std::endl;
173+ std::wcout << L" Found " << dllsToInject.size () << L" plugin(s) to inject from " << pluginsDir << std::endl;
174+ for (const auto & dll : dllsToInject) {
175+ std::wcout << L" - " << dll << std::endl;
176+ }
177+
178+ // Suspended state is needed for Window hooks
179+ PROCESS_INFORMATION pi = {};
180+ STARTUPINFOW si = {};
181+ si.cb = sizeof (si);
182+
183+ std::wstring fullCommandLine = L" \" " + gamePath + L" \" " + gameArgs;
149184
150- NTSTATUS nt = RhCreateAndInject (
151- const_cast <wchar_t *>(gamePath.c_str ()),
152- gameArgs.empty () ? NULL : const_cast <wchar_t *>(gameArgs.c_str ()),
153- 0 , EASYHOOK_INJECT_DEFAULT , dllToInject, NULL ,
154- &injectionInfo, sizeof (InjectionInfo), &processId
155- );
185+ std::wcout << L" Launching game suspended: " << gamePath << std::endl;
186+ std::wcout << L" Injecting with settings for Player " << playerNumber << L" ..." << std::endl;
156187
157- if (nt != 0 ) {
158- std::wcerr << L" Failed to inject DLL: " << RtlGetLastErrorString () << std::endl;
159- Sleep (5000 );
188+ if (!CreateProcess (
189+ NULL ,
190+ const_cast <wchar_t *>(fullCommandLine.c_str ()), // Command line
191+ NULL ,
192+ NULL ,
193+ FALSE ,
194+ CREATE_SUSPENDED ,
195+ NULL ,
196+ NULL ,
197+ &si, // StartupInfo
198+ &pi // ProcessInfo
199+ )) {
200+ Sleep (7000 );
201+ std::wcerr << L" Failed to create process: " << GetLastError () << std::endl;
202+ std::wcerr << L" Command: " << fullCommandLine << std::endl;
203+ // system("pause");
160204 return 1 ;
161205 }
162206
207+ DWORD processId = pi.dwProcessId ;
208+ bool allInjectionsSucceeded = true ;
209+
210+ for (const auto & dllPath : dllsToInject) {
211+ std::wcout << L" Injecting " << dllPath.substr (dllPath.find_last_of (L" \\ /" ) + 1 ) << L" into process " << processId << L" ..." << std::endl;
212+
213+ NTSTATUS nt = RhInjectLibrary (
214+ processId,
215+ 0 ,
216+ EASYHOOK_INJECT_DEFAULT ,
217+ const_cast <wchar_t *>(dllPath.c_str ()),
218+ const_cast <wchar_t *>(dllPath.c_str ()),
219+ &injectionInfo,
220+ sizeof (InjectionInfo)
221+ );
222+
223+ if (nt != 0 ) {
224+ std::wcerr << L" Failed to inject DLL " << dllPath << L" : " << RtlGetLastErrorString () << std::endl;
225+ allInjectionsSucceeded = false ;
226+ // We can choose to stop or continue; let's continue
227+ }
228+ }
229+
230+ if (!allInjectionsSucceeded) {
231+ Sleep (3000 );
232+ std::wcerr << L" Warning: One or more DLLs failed to inject. Attempting to resume process anyway." << std::endl;
233+ }
234+ else {
235+ std::wcout << L" All injections successful." << std::endl;
236+ }
237+
238+ std::wcout << L" Resuming game process..." << std::endl;
239+ ResumeThread (pi.hThread );
240+
241+ CloseHandle (pi.hProcess );
242+ CloseHandle (pi.hThread );
243+
163244 std::wcout << L" Successfully launched and injected into process " << processId << L" . The launcher will now exit." << std::endl;
164245
165246 return 0 ;
0 commit comments