Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

193 lines
4.9 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #ifdef _WIN32
  7. #include "SteamAppStartup.h"
  8. #define WIN32_LEAN_AND_MEAN
  9. #include <assert.h>
  10. #include <windows.h>
  11. #include <process.h>
  12. #include <direct.h>
  13. #include <stdio.h>
  14. #include <sys/stat.h>
  15. #define STEAM_PARM "-steam"
  16. void LaunchSelfViaSteam(const char *params);
  17. bool FileExists(const char *fileName)
  18. {
  19. struct _stat statbuf;
  20. return (_stat(fileName, &statbuf) == 0);
  21. }
  22. //-----------------------------------------------------------------------------
  23. // Purpose: Launches steam if necessary
  24. //-----------------------------------------------------------------------------
  25. bool ShouldLaunchAppViaSteam(const char *lpCmdLine, const char *steamFilesystemDllName, const char *stdioFilesystemDllName)
  26. {
  27. // see if steam is on the command line
  28. const char *steamStr = strstr(lpCmdLine, STEAM_PARM);
  29. // check the character following it is a whitespace or null
  30. if (steamStr)
  31. {
  32. const char *postChar = steamStr + strlen(STEAM_PARM);
  33. if (*postChar == 0 || isspace(*postChar))
  34. {
  35. // we're running under steam already, let the app continue
  36. return false;
  37. }
  38. }
  39. // we're not running under steam, see which filesystems are available
  40. if (FileExists(stdioFilesystemDllName))
  41. {
  42. // we're being run with a stdio filesystem, so we can continue without steam
  43. return false;
  44. }
  45. // make sure we have a steam filesystem available
  46. if (!FileExists(steamFilesystemDllName))
  47. {
  48. return false;
  49. }
  50. // we have the steam filesystem, and no stdio filesystem, so we must need to be run under steam
  51. // launch steam
  52. LaunchSelfViaSteam(lpCmdLine);
  53. return true;
  54. }
  55. //-----------------------------------------------------------------------------
  56. // Purpose: Handles launching the game indirectly via steam
  57. //-----------------------------------------------------------------------------
  58. void LaunchSelfViaSteam(const char *params)
  59. {
  60. // calculate the details of our launch
  61. char appPath[MAX_PATH];
  62. ::GetModuleFileName((HINSTANCE)GetModuleHandle(NULL), appPath, sizeof(appPath));
  63. // strip out the exe name
  64. char *slash = strrchr(appPath, '\\');
  65. if (slash)
  66. {
  67. *slash = 0;
  68. }
  69. // save out our details to the registry
  70. HKEY hKey;
  71. if (ERROR_SUCCESS == RegOpenKey(HKEY_CURRENT_USER, "Software\\Valve\\Steam", &hKey))
  72. {
  73. DWORD dwType = REG_SZ;
  74. DWORD dwSize = static_cast<DWORD>( strlen(appPath) + 1 );
  75. RegSetValueEx(hKey, "TempAppPath", NULL, dwType, (LPBYTE)appPath, dwSize);
  76. dwSize = static_cast<DWORD>( strlen(params) + 1 );
  77. RegSetValueEx(hKey, "TempAppCmdLine", NULL, dwType, (LPBYTE)params, dwSize);
  78. // clear out the appID (since we don't know it yet)
  79. dwType = REG_DWORD;
  80. int appID = -1;
  81. RegSetValueEx(hKey, "TempAppID", NULL, dwType, (LPBYTE)&appID, sizeof(appID));
  82. RegCloseKey(hKey);
  83. }
  84. // search for an active steam instance
  85. HWND hwnd = ::FindWindow("Valve_SteamIPC_Class", "Hidden Window");
  86. if (hwnd)
  87. {
  88. ::PostMessage(hwnd, WM_USER + 3, 0, 0);
  89. }
  90. else
  91. {
  92. // couldn't find steam, find and launch it
  93. // first, search backwards through our current set of directories
  94. char steamExe[MAX_PATH];
  95. steamExe[0] = 0;
  96. char dir[MAX_PATH];
  97. if (::GetCurrentDirectoryA(sizeof(dir), dir))
  98. {
  99. char *slash = strrchr(dir, '\\');
  100. while (slash)
  101. {
  102. // see if steam_dev.exe is in the directory first
  103. slash[1] = 0;
  104. strcat(slash, "steam_dev.exe");
  105. FILE *f = fopen(dir, "rb");
  106. if (f)
  107. {
  108. // found it
  109. fclose(f);
  110. strcpy(steamExe, dir);
  111. break;
  112. }
  113. // see if steam.exe is in the directory
  114. slash[1] = 0;
  115. strcat(slash, "steam.exe");
  116. f = fopen(dir, "rb");
  117. if (f)
  118. {
  119. // found it
  120. fclose(f);
  121. strcpy(steamExe, dir);
  122. break;
  123. }
  124. // kill the string at the slash
  125. slash[0] = 0;
  126. // move to the previous slash
  127. slash = strrchr(dir, '\\');
  128. }
  129. }
  130. if (!steamExe[0])
  131. {
  132. // still not found, use the one in the registry
  133. HKEY hKey;
  134. if (ERROR_SUCCESS == RegOpenKey(HKEY_CURRENT_USER, "Software\\Valve\\Steam", &hKey))
  135. {
  136. DWORD dwType;
  137. DWORD dwSize = sizeof(steamExe);
  138. RegQueryValueEx( hKey, "SteamExe", NULL, &dwType, (LPBYTE)steamExe, &dwSize);
  139. RegCloseKey( hKey );
  140. }
  141. }
  142. if (!steamExe[0])
  143. {
  144. // still no path, error
  145. ::MessageBox(NULL, "Error running game: could not find steam.exe to launch", "Fatal Error", MB_OK | MB_ICONERROR);
  146. return;
  147. }
  148. // fix any slashes
  149. for (char *slash = steamExe; *slash; slash++)
  150. {
  151. if (*slash == '/')
  152. {
  153. *slash = '\\';
  154. }
  155. }
  156. // change to the steam directory
  157. strcpy(dir, steamExe);
  158. char *delimiter = strrchr(dir, '\\');
  159. if (delimiter)
  160. {
  161. *delimiter = 0;
  162. _chdir(dir);
  163. }
  164. // exec steam.exe, in silent mode, with the launch app param
  165. char *args[4] = { steamExe, "-silent", "-applaunch", NULL };
  166. _spawnv(_P_NOWAIT, steamExe, args);
  167. }
  168. }
  169. #endif // _WIN32