summaryrefslogtreecommitdiff
path: root/engine/cl_check_process.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /engine/cl_check_process.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'engine/cl_check_process.cpp')
-rw-r--r--engine/cl_check_process.cpp316
1 files changed, 316 insertions, 0 deletions
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 <Windows.h>
+#include <winternl.h>
+#include <stdio.h>
+#include <TlHelp32.h>
+#include "strtools.h"
+#include <Psapi.h>
+#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
+}