2 #include "InstallerUtil.h"
3 #include "InstallerMain.h"
6 game_database_t g_games =
9 {NULL, 0, GAME_LIST_NO_GAMES},
10 {NULL, 0, GAME_LIST_NO_GAMES},
11 {NULL, 0, GAME_LIST_NO_GAMES}
14 valve_game_t valve_game_list[] =
16 {_T("counter-strike source"), _T("cstrike"), SOURCE_ENGINE_2004},
17 {_T("day of defeat source"), _T("dod"), SOURCE_ENGINE_2004},
18 {_T("half-life 2 deathmatch"), _T("hl2mp"), SOURCE_ENGINE_2004},
19 {_T("half-life deathmatch source"), _T("hl1mp"), SOURCE_ENGINE_2004},
20 {_T("team fortress 2"), _T("tf"), SOURCE_ENGINE_2007},
24 valve_game_t valve_server_list[] =
26 {_T("source dedicated server"), NULL, SOURCE_ENGINE_2004},
27 {_T("source 2007 dedicated server"), NULL, SOURCE_ENGINE_2007},
31 int IsValidFolder(const TCHAR *path)
34 TCHAR gameinfo_file[MAX_PATH];
36 UTIL_PathFormat(gameinfo_file, sizeof(gameinfo_file), _T("%s\\gameinfo.txt"), path);
38 if ((attr = GetFileAttributes(gameinfo_file)) == INVALID_FILE_ATTRIBUTES)
40 return GAMEINFO_DOES_NOT_EXIST;
43 if ((attr & FILE_ATTRIBUTE_READONLY) == FILE_ATTRIBUTE_READONLY)
45 return GAMEINFO_IS_READ_ONLY;
48 if ((attr & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY)
50 return GAMEINFO_DOES_NOT_EXIST;
53 return GAMEINFO_IS_USABLE;
56 void DisplayBadFolderDialog(HWND hDlg, int reason)
58 TCHAR message_string[255];
61 if (reason == GAMEINFO_DOES_NOT_EXIST)
63 resource = IDS_NO_GAMEINFO;
65 else if (reason == GAMEINFO_IS_READ_ONLY)
67 resource = IDS_READONLY_GAMEINFO;
74 if (LoadString(g_hInstance,
77 sizeof(message_string) / sizeof(TCHAR)
85 _T("SourceMod Installer"),
86 MB_OK|MB_ICONWARNING);
89 game_list_t *MakeGameList(const TCHAR *name)
91 game_list_t *gl = (game_list_t *)malloc(sizeof(game_list_t));
93 UTIL_Format(gl->root_name,
94 sizeof(gl->root_name) / sizeof(TCHAR),
103 void AttachGameListToGroup(game_group_t *group, game_list_t *gl)
105 if (group->lists == NULL)
107 group->lists = (game_list_t **)malloc(sizeof(game_list_t *));
111 group->lists = (game_list_t **)realloc(group->lists,
112 sizeof(game_list_t *) * (group->list_count + 1));
115 group->lists[group->list_count] = gl;
119 void AttachModToGameList(game_list_t *gl, unsigned int mod_id)
121 if (gl->games == NULL)
123 gl->games = (unsigned int *)malloc(sizeof(unsigned int));
127 gl->games = (unsigned int *)realloc(gl->games,
128 sizeof(unsigned int) * (gl->game_count + 1));
131 gl->games[gl->game_count] = mod_id;
135 unsigned int AddModToList(game_database_t *db, const game_info_t *mod_info)
137 /* Check if a matching game already exists */
138 for (unsigned int i = 0; i < db->game_count; i++)
140 if (tstrcasecmp(mod_info->game_path, db->game_list[i].game_path) == 0)
146 if (db->game_list == NULL)
148 db->game_list = (game_info_t *)malloc(sizeof(game_info_t));
152 db->game_list = (game_info_t *)realloc(db->game_list,
153 sizeof(game_info_t) * (db->game_count + 1));
156 memcpy(&db->game_list[db->game_count], mod_info, sizeof(game_info_t));
159 return db->game_count - 1;
162 bool TryToAddMod(const TCHAR *path, int eng_type, game_database_t *db, unsigned int *id)
165 TCHAR gameinfo_path[MAX_PATH];
167 UTIL_PathFormat(gameinfo_path,
168 sizeof(gameinfo_path),
169 _T("%s\\gameinfo.txt"),
172 if ((fp = _tfopen(gameinfo_path, _T("rt"))) == NULL)
179 char key[256], value[256];
180 while (!feof(fp) && fgets(buffer, sizeof(buffer), fp) != NULL)
182 if ((pos = BreakStringA(buffer, key, sizeof(key))) == -1)
186 if ((pos = BreakStringA(&buffer[pos], value, sizeof(value))) == -1)
190 if (strcmp(key, "game") == 0)
195 AnsiToUnicode(value, mod.name, sizeof(mod.name));
196 UTIL_Format(mod.game_path, sizeof(mod.game_path), _T("%s"), path);
197 mod.source_engine = eng_type;
199 got_id = AddModToList(db, &mod);
217 void AddModsFromFolder(const TCHAR *path,
224 TCHAR temp_path[MAX_PATH];
225 TCHAR search_path[MAX_PATH];
228 UTIL_Format(search_path,
233 if ((hFind = FindFirstFile(search_path, &fd)) == INVALID_HANDLE_VALUE)
240 if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY)
245 if (tstrcasecmp(fd.cFileName, _T(".")) == 0
246 || tstrcasecmp(fd.cFileName, _T("..")) == 0)
251 UTIL_PathFormat(temp_path,
256 if (TryToAddMod(temp_path, eng_type, db, &mod_id))
258 AttachModToGameList(gl, mod_id);
260 } while (FindNextFile(hFind, &fd));
265 void GetSteamGames(game_database_t *db)
271 TCHAR temp_path[MAX_PATH];
272 TCHAR steam_path[MAX_PATH];
273 TCHAR steamapps_path[MAX_PATH];
275 if (RegOpenKeyEx(HKEY_CURRENT_USER,
276 _T("Software\\Valve\\Steam"),
279 &hkPath) != ERROR_SUCCESS)
281 db->listen.error_code = GAME_LIST_CANT_READ;
282 db->dedicated.error_code = GAME_LIST_CANT_READ;
286 dwLen = sizeof(steam_path) / sizeof(TCHAR);
287 if (RegQueryValueEx(hkPath,
292 &dwLen) != ERROR_SUCCESS)
295 db->listen.error_code = GAME_LIST_CANT_READ;
296 db->dedicated.error_code = GAME_LIST_CANT_READ;
300 UTIL_PathFormat(steamapps_path,
301 sizeof(steamapps_path) / sizeof(TCHAR),
302 _T("%s\\steamapps\\*.*"),
305 if ((hFind = FindFirstFile(steamapps_path, &fd)) == INVALID_HANDLE_VALUE)
308 db->listen.error_code = GAME_LIST_CANT_READ;
309 db->dedicated.error_code = GAME_LIST_CANT_READ;
315 if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY)
320 if (tstrcasecmp(fd.cFileName, _T(".")) == 0
321 || tstrcasecmp(fd.cFileName, _T("..")) == 0)
326 /* If we get a folder called "SourceMods," look for third party mods */
327 if (tstrcasecmp(fd.cFileName, _T("SourceMods")) == 0)
329 game_list_t *gl = MakeGameList(_T("Third-Party Games"));
331 UTIL_PathFormat(temp_path,
332 sizeof(temp_path) / sizeof(TCHAR),
333 _T("%s\\steamapps\\%s"),
337 AddModsFromFolder(temp_path, SOURCE_ENGINE_UNKNOWN, db, gl);
341 AttachGameListToGroup(&db->listen, gl);
350 /* Look for listenserver games */
351 game_list_t *gl = MakeGameList(fd.cFileName);
353 for (unsigned int i = 0; valve_game_list[i].folder != NULL; i++)
356 UTIL_PathFormat(temp_path,
357 sizeof(temp_path) / sizeof(TCHAR),
358 _T("%s\\steamapps\\%s\\%s\\%s"),
361 valve_game_list[i].folder,
362 valve_game_list[i].subfolder);
363 if (TryToAddMod(temp_path, valve_game_list[i].eng_type, db, &mod_id))
365 AttachModToGameList(gl, mod_id);
371 AttachGameListToGroup(&db->listen, gl);
378 /* Look for dedicated games */
379 gl = MakeGameList(fd.cFileName);
381 for (unsigned int i = 0; valve_server_list[i].folder != NULL; i++)
383 UTIL_PathFormat(temp_path,
384 sizeof(temp_path) / sizeof(TCHAR),
385 _T("%s\\steamapps\\%s\\%s"),
388 valve_server_list[i].folder);
389 AddModsFromFolder(temp_path, valve_server_list[i].eng_type, db, gl);
394 AttachGameListToGroup(&db->dedicated, gl);
402 } while (FindNextFile(hFind, &fd));
408 void GetStandaloneGames(game_database_t *db)
411 DWORD dwLen, dwType, dwAttr;
412 TCHAR temp_path[MAX_PATH];
413 TCHAR hlds_path[MAX_PATH];
414 game_list_t *games_standalone;
416 if (RegOpenKeyEx(HKEY_CURRENT_USER,
417 _T("Software\\Valve\\HLServer"),
420 &hkPath) != ERROR_SUCCESS)
422 db->standalone.error_code = GAME_LIST_CANT_READ;
426 dwLen = sizeof(hlds_path) / sizeof(TCHAR);
427 if (RegQueryValueEx(hkPath,
432 &dwLen) != ERROR_SUCCESS)
435 db->standalone.error_code = GAME_LIST_CANT_READ;
439 /* Make sure there is a "srcds.exe" file */
440 UTIL_PathFormat(temp_path,
441 sizeof(temp_path) / sizeof(TCHAR),
444 dwAttr = GetFileAttributes(temp_path);
445 if (dwAttr == INVALID_FILE_ATTRIBUTES)
447 db->standalone.error_code = GAME_LIST_HALFLIFE1;
451 games_standalone = MakeGameList(_T("Standalone"));
453 /* If there is an "orangebox" sub folder, we can make a better guess
454 * at the engine state.
456 UTIL_PathFormat(temp_path,
457 sizeof(temp_path) / sizeof(TCHAR),
460 dwAttr = GetFileAttributes(temp_path);
461 if (dwAttr != INVALID_FILE_ATTRIBUTES
462 && ((dwAttr & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY))
464 AddModsFromFolder(temp_path, SOURCE_ENGINE_2007, db, games_standalone);
467 /* Add everything from the server */
468 AddModsFromFolder(hlds_path, SOURCE_ENGINE_2004, db, games_standalone);
470 if (games_standalone->game_count)
472 AttachGameListToGroup(&db->standalone, games_standalone);
476 free(games_standalone);
482 void DisplayBadGamesDialog(HWND hWnd, int reason)
487 if (reason == GAME_LIST_CANT_READ)
489 idc = IDS_GAME_FAIL_READ;
491 else if (reason == GAME_LIST_HALFLIFE1)
493 idc = IDS_GAME_FAIL_HL1;
495 else if (reason == GAME_LIST_NO_GAMES)
497 idc = IDS_GAME_FAIL_NONE;
504 if (LoadString(g_hInstance,
507 sizeof(message) / sizeof(TCHAR)) == 0)
514 _T("SourceMod Installer"),
515 MB_OK|MB_ICONWARNING);
518 int _ModIdCompare(const void *item1, const void *item2)
520 unsigned int mod_id1 = *(unsigned int *)item1;
521 unsigned int mod_id2 = *(unsigned int *)item2;
523 return tstrcasecmp(g_games.game_list[mod_id1].name, g_games.game_list[mod_id2].name);
526 int _GroupCompare(const void *item1, const void *item2)
528 game_list_t *g1 = *(game_list_t **)item1;
529 game_list_t *g2 = *(game_list_t **)item2;
531 return tstrcasecmp(g1->root_name, g2->root_name);
534 void SortGameGroup(game_group_t *group)
536 qsort(group->lists, group->list_count, sizeof(game_list_t *), _GroupCompare);
538 for (unsigned int i = 0; i < group->list_count; i++)
540 qsort(group->lists[i]->games,
541 group->lists[i]->game_count,
542 sizeof(unsigned int),
550 GetStandaloneGames(&g_games);
551 GetSteamGames(&g_games);
552 SortGameGroup(&g_games.dedicated);
553 SortGameGroup(&g_games.listen);
554 SortGameGroup(&g_games.standalone);
557 void ReleaseGameGroup(game_group_t *group)
559 for (unsigned int i = 0; i < group->list_count; i++)
561 free(group->lists[i]->games);
562 free(group->lists[i]);
569 ReleaseGameGroup(&g_games.dedicated);
570 ReleaseGameGroup(&g_games.listen);
571 ReleaseGameGroup(&g_games.standalone);
572 free(g_games.game_list);
573 memset(&g_games, 0, sizeof(g_games));