@@ -278,6 +278,9 @@ std::filesystem::path get_link_dir(ShortcutsDestination destination, const std::
278278std::filesystem::path GetIconPath (const char *icon_path_, const char *game_id)
279279{
280280 auto icon_path = std::filesystem::u8path (icon_path_);
281+ if (!icon_path.is_absolute ()) {
282+ icon_path = std::filesystem::absolute (icon_path);
283+ }
281284
282285 if (icon_path.filename () != " vpatch.exe" )
283286 return icon_path;
@@ -298,27 +301,53 @@ std::filesystem::path GetIconPath(const char *icon_path_, const char *game_id)
298301 return icon_path;
299302}
300303
304+ ShortcutsType DecideAutoShortcutType (ShortcutsDestination destination, const std::filesystem::path& link_dir, const std::filesystem::path& thcrap_dir_relative)
305+ {
306+ if (destination == SHDESTINATION_DESKTOP || destination == SHDESTINATION_START_MENU) {
307+ // Assume thcrap and the shortcut are in completely different emplacements.
308+ // Both are unlikely to be moved.
309+ if (OS_is_wine ()) {
310+ // Wine doesn't work really well with shortcuts
311+ return SHTYPE_WRAPPER_ABSPATH;
312+ }
313+ return SHTYPE_SHORTCUT;
314+ }
315+ else if (destination == SHDESTINATION_THCRAP_DIR || destination == SHDESTINATION_GAMES_DIRECTORY) {
316+ // SHDESTINATION_THCRAP_DIR:
317+ // The shortcuts are part of thcrap, and if thcrap is moved, the shortcuts
318+ // will be moved with it.
319+ // Unless the user wants to move the generated shortcuts. But we can't know
320+ // what the user will do at this point, so we have to make a choice, and this
321+ // one seems better than trying to be smart and unpredictable.
322+
323+ // SHDESTINATION_GAMES_DIRECTORY:
324+ // The shortcuts are part of the games. If the games move and thcrap doesn't move,
325+ // then the games' paths in games.js become broken.
326+ // So we can assume that these shortcuts will always be moved with thcrap, and making
327+ // them relative makes more sense and helps with portable installations.
328+ return SHTYPE_WRAPPER_RELPATH;
329+ }
330+ TH_UNREACHABLE;
331+ }
332+
301333int CreateShortcuts (const char *run_cfg_fn, games_js_entry *games, ShortcutsDestination destination, ShortcutsType shortcut_type)
302334{
303335 LPCWSTR loader_exe = L" thcrap_loader" DEBUG_OR_RELEASE_W L" .exe" ;
304336 auto thcrap_dir = GetThcrapDir ();
305337 auto self_path = thcrap_dir / L" bin" / loader_exe;
306338 auto link_dir = get_link_dir (destination, thcrap_dir);
307339 int ret = 0 ;
340+ // Yay, COM.
341+ HRESULT com_init_succeeded = E_FAIL;
308342
309- if (shortcut_type != SHTYPE_SHORTCUT &&
343+ if (shortcut_type != SHTYPE_AUTO &&
344+ shortcut_type != SHTYPE_SHORTCUT &&
310345 shortcut_type != SHTYPE_WRAPPER_ABSPATH &&
311346 shortcut_type != SHTYPE_WRAPPER_RELPATH) {
312347 log_print (" Error creating shortcuts: invalid parameter for shortcut_type. Please report this error to the developpers.\n " );
313348 return 1 ;
314349 }
315350
316- // Yay, COM.
317- HRESULT com_init_succeded = E_FAIL;
318- if (shortcut_type == SHTYPE_SHORTCUT) {
319- com_init_succeded = CoInitializeEx (NULL , COINIT_MULTITHREADED);
320- }
321-
322351 log_printf (" Creating shortcuts" );
323352
324353 for (size_t i = 0 ; games[i].id ; i++) {
@@ -334,16 +363,24 @@ int CreateShortcuts(const char *run_cfg_fn, games_js_entry *games, ShortcutsDest
334363 auto link_args_w = std::make_unique<wchar_t []>(link_args.length () + 1 );
335364 StringToUTF16 (link_args_w.get (), link_args.c_str (), -1 );
336365
337- if (shortcut_type == SHTYPE_SHORTCUT) {
366+ ShortcutsType local_shortcut_type = shortcut_type;
367+ if (local_shortcut_type == SHTYPE_AUTO) {
368+ local_shortcut_type = DecideAutoShortcutType (destination, link_dir, thcrap_dir);
369+ }
370+
371+ if (local_shortcut_type == SHTYPE_SHORTCUT) {
372+ if (com_init_succeeded == E_FAIL) {
373+ com_init_succeeded = CoInitializeEx (NULL , COINIT_MULTITHREADED);
374+ }
338375 link_path.replace_extension (" lnk" );
339376 if (CreateLink (link_path, self_path, link_args_w.get (), thcrap_dir, icon_path)) {
340377 ret = 1 ;
341378 }
342379 }
343- else if (shortcut_type == SHTYPE_WRAPPER_ABSPATH || shortcut_type == SHTYPE_WRAPPER_RELPATH) {
380+ else if (local_shortcut_type == SHTYPE_WRAPPER_ABSPATH || local_shortcut_type == SHTYPE_WRAPPER_RELPATH) {
344381 link_path.replace_extension (" exe" );
345382 auto exe_args = std::wstring (loader_exe) + L" " + link_args_w.get ();
346- if (!CreateWrapper (link_path, thcrap_dir, loader_exe, exe_args, icon_path, shortcut_type )) {
383+ if (!CreateWrapper (link_path, thcrap_dir, loader_exe, exe_args, icon_path, local_shortcut_type )) {
347384 ret = 1 ;
348385 }
349386 }
@@ -359,7 +396,7 @@ int CreateShortcuts(const char *run_cfg_fn, games_js_entry *games, ShortcutsDest
359396 }
360397 }
361398
362- if (com_init_succeded == S_OK) {
399+ if (com_init_succeeded == S_OK) {
363400 CoUninitialize ();
364401 }
365402 return ret;
0 commit comments