From 3bf9df6b2785fa6d951086978a3e66f49427166a Mon Sep 17 00:00:00 2001 From: FluorescentCIAAfricanAmerican <0934gj3049fk@protonmail.com> Date: Wed, 22 Apr 2020 12:56:21 -0400 Subject: 1 --- engine/cl_check_process.cpp | 316 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 316 insertions(+) create mode 100644 engine/cl_check_process.cpp (limited to 'engine/cl_check_process.cpp') diff --git a/engine/cl_check_process.cpp b/engine/cl_check_process.cpp new file mode 100644 index 0000000..6b959c2 --- /dev/null +++ b/engine/cl_check_process.cpp @@ -0,0 +1,316 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Windows Only, does a check against all other processes to see how many other instances +// of this process is running concurrently +// +//=============================================================================// + +//********************************************************************************************* +// Process Check +#include "cl_check_process.h" +#include "dbg.h" + +#ifdef IS_WINDOWS_PC +#include +#include +#include +#include +#include "strtools.h" +#include +#endif // IS_WINDOWS_PC + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +#ifdef IS_WINDOWS_PC + +#define HANDLE_QUERY_BUFFER_BLOCK_SIZE ( 1 * 1024 * 1024 ) +#define SystemHandleInformation ( (SYSTEM_INFORMATION_CLASS)16 ) +#define STATUS_INFO_LENGTH_MISMATCH ( (NTSTATUS)( 0xC0000004L ) ) + +typedef NTSTATUS (__stdcall *NtQuerySystemInformation1) +( + IN ULONG SysInfoClass, + IN OUT PVOID SystemInformation, + IN ULONG SystemInformationLength, + OUT PULONG RetLen +); + +typedef struct _HANDLE_INFORMATION +{ + DWORD ProcessId; + BYTE ObjectType; + BYTE Flags; + USHORT Handle; + PVOID KernelObject; + ACCESS_MASK GrantedAccess; + +} HANDLE_INFORMATION, *PHANDLE_INFORMATION; + +typedef struct _SYSTEM_HANDLE_INFORMATION +{ + ULONG HandleCount; + HANDLE_INFORMATION HandleInfoArray[ 1 ]; + +} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION; + +// +// Checks Process Count with CreateToolhelp32Snapshot +// +int CheckOtherInstancesRunningWithSnapShot( const char *thisProcessNameShort ) +{ + DWORD nLength; + char otherProcessNameShort[ MAX_PATH ]; + + nLength = MAX_PATH; + + int iSnapShotCount = 0; + + // + HANDLE hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 ); + if( hSnapshot ) + { + PROCESSENTRY32 pe32; + pe32.dwSize = sizeof(PROCESSENTRY32); + if ( Process32First( hSnapshot, &pe32 ) ) + { + do + { + V_FileBase( pe32.szExeFile, otherProcessNameShort, MAX_PATH ); + if ( V_strcmp( thisProcessNameShort, otherProcessNameShort ) == 0 ) + { +// DevMsg( "CreateToolhelp32Snapshot - Process Name [ %s ] - OtherName [ %s ] \n", thisProcessNameShort, pe32.szExeFile ); + // We found an instance of this executable. + iSnapShotCount++; + } + } while( Process32Next( hSnapshot, &pe32 ) ); + } + CloseHandle(hSnapshot); + } + + return iSnapShotCount; +} + +// +// Checks Process Count with QueryFullProcessImageName and OpenProcess +// +int CheckOtherInstancesWithEnumProcess( const char *thisProcessNameShort ) +{ + NTSTATUS status; + BOOL bStatus; + DWORD nLength; + DWORD nBufferSize; + DWORD nLastProcess; + DWORD i; + HANDLE process; + PSYSTEM_HANDLE_INFORMATION pHandleInfo = NULL; + char otherProcessName[ MAX_PATH ]; + char otherProcessNameShort[ MAX_PATH ]; + + HINSTANCE hInst = NULL; + + // Start with a count of zero, since we will find ourselves too. + int iProcessCount = 0; + + // Get the path to the executable for this process. + nLength = MAX_PATH; + + // Query all of the handles in the system. We have to do this in a loop, since we do + // not know how large of a buffer we need. + nBufferSize = 0; + + // Load ntdll.dll so we can Query the system + /* load the ntdll.dll */ + NtQuerySystemInformation1 NtQuerySystemInformation; + + //PVOID Info; + HMODULE hModule = LoadLibrary( "ntdll.dll" ); + if (!hModule) + { + iProcessCount = CHECK_PROCESS_UNSUPPORTED; + goto Cleanup; + } + + while ( TRUE ) + { + // Increase the buffer size and try the query. + if ( pHandleInfo != NULL ) + { + free( pHandleInfo ); + } + + nBufferSize += HANDLE_QUERY_BUFFER_BLOCK_SIZE; + + pHandleInfo = (PSYSTEM_HANDLE_INFORMATION)malloc( nBufferSize ); + + if ( pHandleInfo == NULL ) + { + iProcessCount = CHECK_PROCESS_UNSUPPORTED; + goto Cleanup; + } + + // Query the handles in the system. + NtQuerySystemInformation = (NtQuerySystemInformation1)GetProcAddress(hModule, "NtQuerySystemInformation"); + if ( NtQuerySystemInformation == NULL ) + { + iProcessCount = CHECK_PROCESS_UNSUPPORTED; + goto Cleanup; + } + + status = NtQuerySystemInformation( SystemHandleInformation, pHandleInfo, nBufferSize, NULL ); + + // If our buffer was too small, try again. + if ( status == STATUS_INFO_LENGTH_MISMATCH ) + { + continue; + } + + // If the query failed, return the error. + if ( !NT_SUCCESS( status ) ) + { + iProcessCount = CHECK_PROCESS_UNSUPPORTED; + goto Cleanup; + } + + break; + } + + // + // Walk all of the entries looking for process IDs we have not processed yet. + // Note that this code assumes that handles will be grouped by process, which is + // what Windows does. If that assumption ever turns out to be false, this code + // will have to be altered to keep a list of process IDs already seen. + // + + // Check for the presence of GetModuleFileNameEx + hInst = LoadLibrary( "Psapi.dll" ); + if ( !hInst ) + return CHECK_PROCESS_UNSUPPORTED; + + typedef DWORD (WINAPI *GetProcessImageFileNameFn)(HANDLE, LPTSTR, DWORD); + GetProcessImageFileNameFn fn = (GetProcessImageFileNameFn)GetProcAddress( hInst, +#ifdef UNICODE + "GetProcessImageFileNameW"); +#else + "GetProcessImageFileNameA"); +#endif + + if ( !fn ) + return CHECK_PROCESS_UNSUPPORTED; + + nLastProcess = 0; + + for ( i = 0; i < pHandleInfo->HandleCount; i++ ) + { + if ( pHandleInfo->HandleInfoArray[ i ].ProcessId != nLastProcess ) + { + //nLastProcess = pHandleInfo->HandleInfoArray[ i ].ProcessId; + nLastProcess = pHandleInfo->HandleInfoArray[ i ].ProcessId; + + // + // Try to open a handle to this process. Note that we may not have + // access to all processes, so we ignore errors. + // + process = OpenProcess( PROCESS_QUERY_INFORMATION, + FALSE, + nLastProcess ); + + if ( process != NULL ) + { + // Query the name of the executable for the process we opened. If the query + // fails, we ignore this process. + nLength = MAX_PATH; + + bStatus = fn( process, otherProcessName, nLength ); + + if ( bStatus ) + { + // + // We have the process name. See if it is the same name as our process. + // + V_FileBase( otherProcessName, otherProcessNameShort, MAX_PATH ); + + if ( V_strcmp( thisProcessNameShort, otherProcessNameShort ) == 0 ) + { + // We found an instance of this executable. +// DevMsg( "EnumProcess - Process Name [ %s ] - OtherName [ %s ] \n", thisProcessNameShort, otherProcessName ); + iProcessCount++; + } + } + + CloseHandle( process ); + } + } + } + +Cleanup: + + // Free allocated resources. + if ( pHandleInfo != NULL ) + { + free( pHandleInfo ); + } + + if ( hInst != NULL ) + { + FreeLibrary( hInst ); + } + + if ( hModule != NULL ) + { + FreeLibrary( hModule ); + } + + return iProcessCount; +} +#endif // IS_WINDOWS_PC + +int CheckOtherInstancesRunning( void ) +{ +#ifdef IS_WINDOWS_PC + + BOOL bStatus = 0; + DWORD nLength = MAX_PATH; + char thisProcessName[ MAX_PATH ]; + char thisProcessNameShort[ MAX_PATH ]; + + // Load the pspapi to get our current process' name + HINSTANCE hInst = LoadLibrary( "Psapi.dll" ); + if ( hInst ) + { + typedef DWORD (WINAPI *GetProcessImageFileNameFn)(HANDLE, LPTSTR, DWORD); + GetProcessImageFileNameFn fn = (GetProcessImageFileNameFn)GetProcAddress( hInst, +#ifdef UNICODE + "GetProcessImageFileNameW"); +#else + "GetProcessImageFileNameA"); +#endif + if ( fn ) + { + bStatus = fn( GetCurrentProcess(), thisProcessName, nLength ); + } + + FreeLibrary( hInst ); + } + + if ( !bStatus ) + { + return CHECK_PROCESS_UNSUPPORTED; + } + + V_FileBase( thisProcessName, thisProcessNameShort, MAX_PATH ); + +// Msg( "Checking Other Instances Running : ProcessShortName [ %s - %s ] \n", thisProcessName, thisProcessNameShort ); + + int iSnapShotCount = CheckOtherInstancesRunningWithSnapShot( thisProcessNameShort ); + if ( iSnapShotCount > 1 ) + { + return iSnapShotCount; + } + + int iEnumCount = CheckOtherInstancesWithEnumProcess( thisProcessNameShort ); + return iEnumCount > iSnapShotCount ? iEnumCount : iSnapShotCount; +#endif // IS_WINDOWS_PC + + return CHECK_PROCESS_UNSUPPORTED; // -1 UNSUPPORTED +} -- cgit v1.2.3