Hi, I have a problem that happens only sometimes when I'm trying to close a mutex handle of a process that I'm creating. The goal is to be able to open the game client several times.
I begin with creating a process:
Code:
PROCESS_INFORMATION pi;
STARTUPINFOA si = {sizeof(si)};
char szAppPath[MAX_PATH] = "";
GetModuleFileNameA(NULL, szAppPath, MAX_PATH);
std::string strAppDirectory = szAppPath;
strAppDirectory = strAppDirectory.substr(0, strAppDirectory.rfind("\\")) + "\\game.exe";
CreateProcessA(strAppDirectory.c_str(), NULL,
NULL, NULL, false, NORMAL_PRIORITY_CLASS, NULL,
strAppDirectory.substr(0, strAppDirectory.rfind("\\")).c_str(),
&si, &pi);
Then I check if the process has been created:
Code:
if (!pi.hProcess)
{
MessageBoxA(NULL, "Please place this program inside your game folder.", "ERROR", MB_OK);
}
else if it has, we begin to find it's mutex handle that we wish to close:
Code:
SystemHandle* handle = SystemHandle::EnumerateProcessHandles(pi.dwProcessId);
please find the entire SystemHandle class here:
Code:
#include "SystemHandle.h"
#include <iostream>
SystemHandle::SystemHandle(SYSTEM_HANDLE handle)
{
this->systemHandle = handle;
// cout << this->systemHandle.dwProcessId << "\n";
this->process = OpenProcess(PROCESS_ALL_ACCESS, 0, this->systemHandle.dwProcessId);
GetHandleName();
}
SystemHandle::~SystemHandle()
{
if (this->process) CloseHandle(this->process);
}
SYSTEM_HANDLE SystemHandle::GetNativeSystemHandle() { return this->systemHandle; }
HANDLE SystemHandle::GetNativeHandle() { return (HANDLE)this->systemHandle.wValue; }
char* SystemHandle::GetName() { return this->handleName; }
NTSTATUS SystemHandle::Close(bool asMutex)
{
NTSTATUS cResult;
HANDLE hFake;
NTSTATUS duplicateObject;
cout << &duplicateObject << "\n";
cout << &hFake << "\n";
cout << this->process << "\n";
cout << GetNativeHandle() << "\n";
duplicateObject = NtDuplicateObject(this->process, this->GetNativeHandle(), GetCurrentProcess(), &hFake, 0, 0, DUPLICATE_CLOSE_SOURCE);
std::cout << "\nduplicateObject: " << duplicateObject << ", GetLastError: " << GetLastError() << ", DisplayError: " << ", Success: " << NT_SUCCESS(duplicateObject) << "\n";
if (NT_SUCCESS(duplicateObject))
{
if (asMutex)
{
ReleaseMutex(hFake);
}
cResult = NtClose(hFake);
cout << cResult << "\n";
}
free(&hFake);
free(&duplicateObject);
hFake = NULL;
duplicateObject = NULL;
return cResult;
}
void SystemHandle::GetHandleName()
{
HANDLE hFake;
char* objectName = NULL;
LPVOID lpMessageBuffer = NULL;
HMODULE Hand = LoadLibraryA("ntdll.dll");
// NTSTATUS duplicateObject = DuplicateHandle(this->process, this->GetNativeHandle(), GetCurrentProcess(), &hFake, 0, FALSE, DUPLICATE_SAME_ACCESS);
NTSTATUS duplicateObject = NtDuplicateObject(this->process, this->GetNativeHandle(), GetCurrentProcess(), &hFake, 0, 0, 0);
// std::cout << "\nduplicateObject: " << duplicateObject << ", GetLastError: " << GetLastError() << ", DisplayError: " << DisplayError(duplicateObject, lpMessageBuffer, Hand) << ", Success: " << NT_SUCCESS(duplicateObject) << "\n";
if (NT_SUCCESS(duplicateObject))
{
POBJECT_TYPE_INFORMATION typeInfo = (POBJECT_TYPE_INFORMATION)new BYTE[0x1000];
PUNICODE_STRING nameInfo = (PUNICODE_STRING)new BYTE[0x1000];
DWORD read;
NTSTATUS statusType = NtQueryObject(hFake, ObjectTypeInformation, typeInfo, 0x1000, &read);
NTSTATUS statusName = NtQueryObject(hFake, ObjectNameInformation, nameInfo, 0x1000, &read);
objectName = new char[nameInfo->Length];
// std::cout << "statusType: " << statusType << ", GetLastError: " << GetLastError() << ", DisplayError: " << DisplayError(statusType, lpMessageBuffer, Hand) << ", Success: " << NT_SUCCESS(statusType) << "\n";
// std::cout << "statusName: " << statusName << ", GetLastError: " << GetLastError() << ", DisplayError: " << DisplayError(statusName, lpMessageBuffer, Hand) << ", Success: " << NT_SUCCESS(statusName) << "\n";
if (NT_SUCCESS(statusType) && NT_SUCCESS(statusName))
{
if (typeid(objectName) == typeid(char*)) // make strcpy_s stop crying
{
WideToChar(objectName, nameInfo->Buffer, nameInfo->Length);
strcpy_s(this->handleName, objectName);
}
}
delete nameInfo;
delete typeInfo;
}
// Free the buffer allocated by the system.
LocalFree(lpMessageBuffer);
FreeLibrary(Hand);
if (hFake) CloseHandle(hFake);
}
LPVOID SystemHandle::DisplayError(DWORD NTStatusMessage, LPVOID lpMessageBuffer, HMODULE Hand)
{
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE,
Hand,
NTStatusMessage,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMessageBuffer,
0,
NULL);
// Now display the string.
return lpMessageBuffer;
}
SystemHandle* SystemHandle::EnumerateProcessHandles(DWORD procID)
{
SystemHandle* ret;
PSYSTEM_HANDLE_INFORMATION pSysHandleInformation = (PSYSTEM_HANDLE_INFORMATION)new BYTE[0x2000];
DWORD needed = 0;
if(!NT_SUCCESS(NtQuerySystemInformation(SystemHandleInformation, pSysHandleInformation, 0x2000, &needed)))
{ //We need a larger buffer
delete pSysHandleInformation;
pSysHandleInformation = (PSYSTEM_HANDLE_INFORMATION)new BYTE[needed];
if (NT_SUCCESS(NtQuerySystemInformation(SystemHandleInformation, pSysHandleInformation, needed, &needed)))
{
for (size_t i = 0, ilen = pSysHandleInformation->dwCount; i < ilen; ++i)
{
if (pSysHandleInformation->Handles[i].dwProcessId == procID)
{
cout << "1\n";
ret = new SystemHandle(pSysHandleInformation->Handles[i]);
if (strcmp(ret->GetName(), "\\Sessions\\1\\BaseNamedObjects\\GameClientMutex") == 0)
{
cout << "\nfound it\n";
cout << ret->GetName() << "\n";
break;
}
}
}
}
}
else
{
for (size_t i = 0, ilen = pSysHandleInformation->dwCount; i < ilen; ++i)
{
if (pSysHandleInformation->Handles[i].dwProcessId == procID)
{
cout << "2\n";
ret = new SystemHandle(pSysHandleInformation->Handles[i]);
if (strcmp(ret->GetName(), "\\Sessions\\1\\BaseNamedObjects\\GameClientMutex") == 0)
{
cout << "\nfound it\n";
cout << ret->GetName() << "\n";
break;
}
}
}
}
delete pSysHandleInformation;
return ret;
}
The times that it does crash we do it at row 29 in SystemHandle where you find "this->process"
The error is:
Application "\??\C:\game\game.exe" found in cache
First-chance exception at 0x00407A24 in game.exe: 0xC0000005: Access violation reading location 0x00001E9C.
Unhandled exception at 0x00407A24 in game.exe: 0xC0000005: Access violation reading location 0x00001E9C.
Would anybody know why this happens sometimes and what I am doing so wrong?
- - - Updated - - -
this may be because "ret" in "SystemHandle::EnumerateProcessHandles" sometimes does not find the process that we create, and then try to OpenProcess() a process that does not exist?