diff options
Diffstat (limited to 'utils/itemtest_lib/systemutils.cpp')
| -rw-r--r-- | utils/itemtest_lib/systemutils.cpp | 265 |
1 files changed, 265 insertions, 0 deletions
diff --git a/utils/itemtest_lib/systemutils.cpp b/utils/itemtest_lib/systemutils.cpp new file mode 100644 index 0000000..00b307f --- /dev/null +++ b/utils/itemtest_lib/systemutils.cpp @@ -0,0 +1,265 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Stuff which interacts with system libraries +// +//============================================================================= + + +// Windows includes +#include <windows.h> +#include <direct.h> + + +// Valve includes +#include "itemtest/itemtest.h" +#include "tier1/fmtstr.h" + + +// Last include +#include "tier0/memdbgon.h" + + +//----------------------------------------------------------------------------- +// Globals +//----------------------------------------------------------------------------- +HANDLE g_hChildStd_OUT_Rd = NULL; +HANDLE g_hChildStd_OUT_Wr = NULL; + +HANDLE g_hInputFile = NULL; + +#define BUFSIZE 4096 + + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +bool CItemUpload::CreateDirectory( const char *pszDirectory ) +{ + char szBuf[ BUFSIZE ]; + V_strncpy( szBuf, pszDirectory, 1024 ); + + for ( int i = 0; i < V_strlen( szBuf ); ++i ) + { + if ( szBuf[i] == '/' || szBuf[i] == '\\' ) + { + szBuf[i] = '\0'; + mkdir( szBuf ); + szBuf[i] = CORRECT_PATH_SEPARATOR; + } + } + + mkdir( szBuf ); + + return true; +} + + +//----------------------------------------------------------------------------- +// Read output from the child process's pipe for STDOUT +// and write to the parent process's pipe for STDOUT. +// Stop when there is no more data. +//----------------------------------------------------------------------------- +static void ReadFromPipe( CItemLog *pLog ) +{ + DWORD dwRead; + char chBuf[BUFSIZE + 1]; + BOOL bSuccess = FALSE; + + // Close the write end of the pipe before reading from the + // read end of the pipe, to control child process execution. + // The pipe is assumed to have enough buffer space to hold the + // data the child process has already written to it. + + if ( !CloseHandle( g_hChildStd_OUT_Wr ) ) + return; + + // TODO: Prefix each line, print in color? + + for (;;) + { + // This can hang if the process is waiting for input, for example... + bSuccess = ReadFile( g_hChildStd_OUT_Rd, chBuf, BUFSIZE, &dwRead, NULL ); + + if ( !bSuccess || dwRead == 0 ) + break; + + chBuf[dwRead] = '\0'; + + pLog->Warning( chBuf ); + } +} + + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +bool CItemUpload::RunCommandLine( const char *pszCmdLine, const char *pszWorkingDir, CItemLog *pLog ) +{ + bool bOk = false; + + Msg( "Launching: %s\n", pszCmdLine ); + Msg( "Directory: %s\n", pszWorkingDir ); + + if ( pLog ) + { + SECURITY_ATTRIBUTES saAttr; + + // Set the bInheritHandle flag so pipe handles are inherited. + saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); + saAttr.bInheritHandle = TRUE; + saAttr.lpSecurityDescriptor = NULL; + + // Create a pipe for the child process's STDOUT. + if ( !CreatePipe( &g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0 ) ) + return false; + + // Ensure the read handle to the pipe for STDOUT is not inherited. + if ( !SetHandleInformation( g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0 ) ) + return false; + } + + // Create the child process. + PROCESS_INFORMATION piProcInfo; + STARTUPINFO siStartInfo; + + // Set up members of the PROCESS_INFORMATION structure. + V_memset( &piProcInfo, 0, sizeof( PROCESS_INFORMATION ) ); + + // Set up members of the STARTUPINFO structure. + // This structure specifies the STDIN and STDOUT handles for redirection. + V_memset( &siStartInfo, 0, sizeof( STARTUPINFO ) ); + siStartInfo.cb = sizeof( STARTUPINFO ); + + if ( pLog ) + { + siStartInfo.hStdError = g_hChildStd_OUT_Wr; + siStartInfo.hStdOutput = g_hChildStd_OUT_Wr; + siStartInfo.dwFlags |= STARTF_USESTDHANDLES; + } + + // Create the child process. + const BOOL bSuccess = CreateProcess(NULL, + const_cast< char * >( pszCmdLine ), // command line + NULL, // process security attributes + NULL, // primary thread security attributes + TRUE, // handles are inherited + CREATE_NO_WINDOW, // creation flags + NULL, // use parent's environment + pszWorkingDir, // use parent's current directory + &siStartInfo, // STARTUPINFO pointer + &piProcInfo ); // receives PROCESS_INFORMATION + + // If an error occurs, return + if ( !bSuccess ) + return false; + + if ( pLog ) + { + ReadFromPipe( pLog ); + + WaitForSingleObject( piProcInfo.hProcess, INFINITE ); + + bOk = false; + + DWORD nExitCode = 0; + if ( GetExitCodeProcess( piProcInfo.hProcess, &nExitCode ) ) + { + bOk = ( nExitCode == 0 ); + } + + CloseHandle( piProcInfo.hProcess ); + CloseHandle( piProcInfo.hThread ); + } + else + { + bOk = true; + } + + return bOk; +} + + +//----------------------------------------------------------------------------- +// Determine if 2 paths point ot the same file... +// Note: This only works if the file exists +//----------------------------------------------------------------------------- +bool CItemUpload::IsSameFile( const char *szPath1, const char *szPath2 ) +{ + if ( !szPath1 || !szPath2 ) + return false; + + HANDLE handle1 = ::CreateFile( szPath1, 0, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); + HANDLE handle2 = ::CreateFile( szPath2, 0, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); + + bool bResult = false; + + if ( handle1 != NULL && handle2 != NULL ) + { + BY_HANDLE_FILE_INFORMATION fileInfo1; + BY_HANDLE_FILE_INFORMATION fileInfo2; + if ( ::GetFileInformationByHandle( handle1, &fileInfo1 ) && ::GetFileInformationByHandle( handle2, &fileInfo2 ) ) + { + bResult = fileInfo1.dwVolumeSerialNumber == fileInfo2.dwVolumeSerialNumber && + fileInfo1.nFileIndexHigh == fileInfo2.nFileIndexHigh && + fileInfo1.nFileIndexLow == fileInfo2.nFileIndexLow; + } + } + + if ( handle1 != NULL ) + { + ::CloseHandle(handle1); + } + + if ( handle2 != NULL ) + { + ::CloseHandle( handle2 ); + } + + return bResult; +} + + +//----------------------------------------------------------------------------- +// Gets the filename to the current executable +//----------------------------------------------------------------------------- +bool CItemUpload::GetCurrentExecutableFileName( CUtlString &sCurrentExecutableFileName ) +{ + char szModuleFileName[MAX_PATH]; + szModuleFileName[0] = '\0'; + + if ( !::GetModuleFileName( (HMODULE)NULL, szModuleFileName, ARRAYSIZE( szModuleFileName ) ) ) + return false; + + sCurrentExecutableFileName = szModuleFileName; + + return true; +} + + +//----------------------------------------------------------------------------- +// Get the install location of the app from the registry via +// +// HKEY_LOCAL_MACHINE : +// "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Steam App %d" +// +//----------------------------------------------------------------------------- +bool CItemUpload::GetSteamAppInstallLocation( CUtlString &sSteamAppInstallLocation, int nAppId ) +{ + HKEY hKey; + char szSteamAppInstallLocation[ 65536 ] = ""; + + const CFmtStr sRegKey( "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Steam App %d", nAppId ); + + if ( ERROR_SUCCESS == RegOpenKey( HKEY_LOCAL_MACHINE, sRegKey.String(), &hKey ) ) + { + DWORD dwSize = sizeof( szSteamAppInstallLocation ); + RegQueryValueEx( hKey, "InstallLocation", NULL, NULL, (LPBYTE)szSteamAppInstallLocation, &dwSize ); + RegCloseKey( hKey ); + + sSteamAppInstallLocation = szSteamAppInstallLocation; + + return true; + } + + return false; +}
\ No newline at end of file |