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.

264 lines
7.3 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Stuff which interacts with system libraries
  4. //
  5. //=============================================================================
  6. // Windows includes
  7. #include <windows.h>
  8. #include <direct.h>
  9. // Valve includes
  10. #include "itemtest/itemtest.h"
  11. #include "tier1/fmtstr.h"
  12. // Last include
  13. #include "tier0/memdbgon.h"
  14. //-----------------------------------------------------------------------------
  15. // Globals
  16. //-----------------------------------------------------------------------------
  17. HANDLE g_hChildStd_OUT_Rd = NULL;
  18. HANDLE g_hChildStd_OUT_Wr = NULL;
  19. HANDLE g_hInputFile = NULL;
  20. #define BUFSIZE 4096
  21. //-----------------------------------------------------------------------------
  22. //
  23. //-----------------------------------------------------------------------------
  24. bool CItemUpload::CreateDirectory( const char *pszDirectory )
  25. {
  26. char szBuf[ BUFSIZE ];
  27. V_strncpy( szBuf, pszDirectory, 1024 );
  28. for ( int i = 0; i < V_strlen( szBuf ); ++i )
  29. {
  30. if ( szBuf[i] == '/' || szBuf[i] == '\\' )
  31. {
  32. szBuf[i] = '\0';
  33. mkdir( szBuf );
  34. szBuf[i] = CORRECT_PATH_SEPARATOR;
  35. }
  36. }
  37. mkdir( szBuf );
  38. return true;
  39. }
  40. //-----------------------------------------------------------------------------
  41. // Read output from the child process's pipe for STDOUT
  42. // and write to the parent process's pipe for STDOUT.
  43. // Stop when there is no more data.
  44. //-----------------------------------------------------------------------------
  45. static void ReadFromPipe( CItemLog *pLog )
  46. {
  47. DWORD dwRead;
  48. char chBuf[BUFSIZE + 1];
  49. BOOL bSuccess = FALSE;
  50. // Close the write end of the pipe before reading from the
  51. // read end of the pipe, to control child process execution.
  52. // The pipe is assumed to have enough buffer space to hold the
  53. // data the child process has already written to it.
  54. if ( !CloseHandle( g_hChildStd_OUT_Wr ) )
  55. return;
  56. // TODO: Prefix each line, print in color?
  57. for (;;)
  58. {
  59. // This can hang if the process is waiting for input, for example...
  60. bSuccess = ReadFile( g_hChildStd_OUT_Rd, chBuf, BUFSIZE, &dwRead, NULL );
  61. if ( !bSuccess || dwRead == 0 )
  62. break;
  63. chBuf[dwRead] = '\0';
  64. pLog->Warning( chBuf );
  65. }
  66. }
  67. //-----------------------------------------------------------------------------
  68. //
  69. //-----------------------------------------------------------------------------
  70. bool CItemUpload::RunCommandLine( const char *pszCmdLine, const char *pszWorkingDir, CItemLog *pLog )
  71. {
  72. bool bOk = false;
  73. Msg( "Launching: %s\n", pszCmdLine );
  74. Msg( "Directory: %s\n", pszWorkingDir );
  75. if ( pLog )
  76. {
  77. SECURITY_ATTRIBUTES saAttr;
  78. // Set the bInheritHandle flag so pipe handles are inherited.
  79. saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
  80. saAttr.bInheritHandle = TRUE;
  81. saAttr.lpSecurityDescriptor = NULL;
  82. // Create a pipe for the child process's STDOUT.
  83. if ( !CreatePipe( &g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0 ) )
  84. return false;
  85. // Ensure the read handle to the pipe for STDOUT is not inherited.
  86. if ( !SetHandleInformation( g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0 ) )
  87. return false;
  88. }
  89. // Create the child process.
  90. PROCESS_INFORMATION piProcInfo;
  91. STARTUPINFO siStartInfo;
  92. // Set up members of the PROCESS_INFORMATION structure.
  93. V_memset( &piProcInfo, 0, sizeof( PROCESS_INFORMATION ) );
  94. // Set up members of the STARTUPINFO structure.
  95. // This structure specifies the STDIN and STDOUT handles for redirection.
  96. V_memset( &siStartInfo, 0, sizeof( STARTUPINFO ) );
  97. siStartInfo.cb = sizeof( STARTUPINFO );
  98. if ( pLog )
  99. {
  100. siStartInfo.hStdError = g_hChildStd_OUT_Wr;
  101. siStartInfo.hStdOutput = g_hChildStd_OUT_Wr;
  102. siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
  103. }
  104. // Create the child process.
  105. const BOOL bSuccess = CreateProcess(NULL,
  106. const_cast< char * >( pszCmdLine ), // command line
  107. NULL, // process security attributes
  108. NULL, // primary thread security attributes
  109. TRUE, // handles are inherited
  110. CREATE_NO_WINDOW, // creation flags
  111. NULL, // use parent's environment
  112. pszWorkingDir, // use parent's current directory
  113. &siStartInfo, // STARTUPINFO pointer
  114. &piProcInfo ); // receives PROCESS_INFORMATION
  115. // If an error occurs, return
  116. if ( !bSuccess )
  117. return false;
  118. if ( pLog )
  119. {
  120. ReadFromPipe( pLog );
  121. WaitForSingleObject( piProcInfo.hProcess, INFINITE );
  122. bOk = false;
  123. DWORD nExitCode = 0;
  124. if ( GetExitCodeProcess( piProcInfo.hProcess, &nExitCode ) )
  125. {
  126. bOk = ( nExitCode == 0 );
  127. }
  128. CloseHandle( piProcInfo.hProcess );
  129. CloseHandle( piProcInfo.hThread );
  130. }
  131. else
  132. {
  133. bOk = true;
  134. }
  135. return bOk;
  136. }
  137. //-----------------------------------------------------------------------------
  138. // Determine if 2 paths point ot the same file...
  139. // Note: This only works if the file exists
  140. //-----------------------------------------------------------------------------
  141. bool CItemUpload::IsSameFile( const char *szPath1, const char *szPath2 )
  142. {
  143. if ( !szPath1 || !szPath2 )
  144. return false;
  145. HANDLE handle1 = ::CreateFile( szPath1, 0, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
  146. HANDLE handle2 = ::CreateFile( szPath2, 0, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
  147. bool bResult = false;
  148. if ( handle1 != NULL && handle2 != NULL )
  149. {
  150. BY_HANDLE_FILE_INFORMATION fileInfo1;
  151. BY_HANDLE_FILE_INFORMATION fileInfo2;
  152. if ( ::GetFileInformationByHandle( handle1, &fileInfo1 ) && ::GetFileInformationByHandle( handle2, &fileInfo2 ) )
  153. {
  154. bResult = fileInfo1.dwVolumeSerialNumber == fileInfo2.dwVolumeSerialNumber &&
  155. fileInfo1.nFileIndexHigh == fileInfo2.nFileIndexHigh &&
  156. fileInfo1.nFileIndexLow == fileInfo2.nFileIndexLow;
  157. }
  158. }
  159. if ( handle1 != NULL )
  160. {
  161. ::CloseHandle(handle1);
  162. }
  163. if ( handle2 != NULL )
  164. {
  165. ::CloseHandle( handle2 );
  166. }
  167. return bResult;
  168. }
  169. //-----------------------------------------------------------------------------
  170. // Gets the filename to the current executable
  171. //-----------------------------------------------------------------------------
  172. bool CItemUpload::GetCurrentExecutableFileName( CUtlString &sCurrentExecutableFileName )
  173. {
  174. char szModuleFileName[MAX_PATH];
  175. szModuleFileName[0] = '\0';
  176. if ( !::GetModuleFileName( (HMODULE)NULL, szModuleFileName, ARRAYSIZE( szModuleFileName ) ) )
  177. return false;
  178. sCurrentExecutableFileName = szModuleFileName;
  179. return true;
  180. }
  181. //-----------------------------------------------------------------------------
  182. // Get the install location of the app from the registry via
  183. //
  184. // HKEY_LOCAL_MACHINE :
  185. // "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Steam App %d"
  186. //
  187. //-----------------------------------------------------------------------------
  188. bool CItemUpload::GetSteamAppInstallLocation( CUtlString &sSteamAppInstallLocation, int nAppId )
  189. {
  190. HKEY hKey;
  191. char szSteamAppInstallLocation[ 65536 ] = "";
  192. const CFmtStr sRegKey( "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Steam App %d", nAppId );
  193. if ( ERROR_SUCCESS == RegOpenKey( HKEY_LOCAL_MACHINE, sRegKey.String(), &hKey ) )
  194. {
  195. DWORD dwSize = sizeof( szSteamAppInstallLocation );
  196. RegQueryValueEx( hKey, "InstallLocation", NULL, NULL, (LPBYTE)szSteamAppInstallLocation, &dwSize );
  197. RegCloseKey( hKey );
  198. sSteamAppInstallLocation = szSteamAppInstallLocation;
  199. return true;
  200. }
  201. return false;
  202. }