launcher.c (3377B)
1 #define WIN32_LEAN_AND_MEAN 2 #include <windows.h> 3 #include <shellapi.h> 4 5 6 #define MSVC_URL "https://www.microsoft.com/en-us/download/details.aspx?id=40784" 7 8 // set shit that's possible here 9 #pragma comment(linker, "/merge:.text=.data") 10 #pragma comment(linker, "/merge:.rdata=.data") 11 12 static void strwcpy(wchar_t* dst, const wchar_t* src) 13 { 14 while (*dst++ = *src++); 15 } 16 17 void* memset(void* dst, int c, size_t len) 18 { 19 for (size_t i = 0; i < len; ++i) 20 ((char *) dst)[i] = c; 21 return dst; 22 } 23 24 static size_t strwlen(const wchar_t* ptr) 25 { 26 const wchar_t* p = ptr; 27 while (*p++); 28 return p - ptr; 29 } 30 31 static int inject_dll(HANDLE proc, wchar_t* fname) 32 { 33 size_t bytes = sizeof(wchar_t) * (strwlen(fname)+1); 34 void* ptr = VirtualAllocEx(proc, NULL, bytes, MEM_COMMIT, PAGE_READWRITE); 35 if (!ptr) return 0; 36 37 if (!WriteProcessMemory(proc, ptr, fname, bytes, NULL)) return 0; 38 39 HANDLE th = CreateRemoteThread( 40 proc, NULL, 0, (LPTHREAD_START_ROUTINE) &LoadLibraryW, ptr, 0, NULL); 41 if (!th) return 0; 42 43 WaitForSingleObject(th, INFINITE); 44 DWORD ret; 45 if (!GetExitCodeThread(th, &ret) || ret == 0) return 0; 46 CloseHandle(th); 47 48 if (!VirtualFreeEx(proc, ptr, 0, MEM_RELEASE)) return 0; 49 50 return 1; 51 } 52 53 static int mymain(void) 54 { 55 HANDLE h = LoadLibraryExA("msvcp120.dll", NULL, LOAD_LIBRARY_AS_DATAFILE); 56 if (h == NULL) 57 { 58 int ret = MessageBoxA( 59 NULL, "Please install MSVC 2013 runtime\n\nOpen download page?", 60 NULL, MB_YESNO | MB_ICONERROR); 61 if (ret == IDYES) 62 ShellExecuteA(NULL, NULL, MSVC_URL, NULL, NULL, SW_SHOWNORMAL); 63 return 1; 64 } 65 CloseHandle(h); 66 67 #define BUF_SIZE 4096 68 wchar_t buf[BUF_SIZE]; 69 GetModuleFileNameW(NULL, buf, BUF_SIZE); 70 buf[BUF_SIZE-1] = 0; // maybe xp 71 72 wchar_t* last_slash = buf; 73 for (wchar_t* ptr = buf; *ptr; ++ptr) 74 if (*ptr == L'\\') 75 last_slash = ptr; 76 77 if (*last_slash != L'\\' || last_slash - buf > BUF_SIZE - 22) 78 { 79 MessageBoxA(NULL, "Wrong module path", NULL, MB_OK | MB_ICONERROR); 80 return 2; 81 } 82 strwcpy(last_slash + 1, L"NeptuniaReBirth3.exe"); 83 84 for (int i = '3';; --i) 85 { 86 last_slash[16] = i; 87 unsigned attrib = GetFileAttributesW(buf); 88 if (attrib != INVALID_FILE_ATTRIBUTES && 89 !(attrib & FILE_ATTRIBUTE_ENCRYPTED)) 90 break; 91 92 if (i == '1') 93 { 94 strwcpy(&last_slash[9], L"VII.exe"); 95 unsigned attrib = GetFileAttributesW(buf); 96 if (attrib != INVALID_FILE_ATTRIBUTES && 97 !(attrib & FILE_ATTRIBUTE_ENCRYPTED)) 98 break; 99 100 MessageBoxA(NULL, "Couldn't find Neptunia", 101 NULL, MB_OK | MB_ICONERROR); 102 return 2; 103 } 104 } 105 106 STARTUPINFOW si; 107 PROCESS_INFORMATION pi; 108 memset(&si, 0, sizeof(si)); 109 memset(&pi, 0, sizeof(pi)); 110 si.cb = sizeof(STARTUPINFO); 111 if (CreateProcessW(buf, GetCommandLineW(), NULL, NULL, FALSE, 112 CREATE_SUSPENDED, NULL, NULL, &si, &pi) == 0) 113 { 114 MessageBoxA(NULL, "Failed to start game", NULL, MB_OK | MB_ICONERROR); 115 return 2; 116 } 117 118 strwcpy(last_slash + 1, L"neptools-server.dll"); 119 if (!inject_dll(pi.hProcess, buf)) 120 { 121 TerminateProcess(pi.hProcess, 0); 122 MessageBoxA(NULL, "DLL injection failed", NULL, MB_OK | MB_ICONERROR); 123 return 3; 124 } 125 126 ResumeThread(pi.hThread); 127 CloseHandle(pi.hProcess); 128 CloseHandle(pi.hThread); 129 return 0; 130 } 131 132 void __cdecl start(void); 133 void __cdecl start(void) 134 { 135 ExitProcess(mymain()); 136 }