SolvedHow to check if the game finished loading?

Posts 112 of 12 · Page 1 of 1
How to check if the game finished loading?
Hey guys, sorry to bother you again.

The problem is I need to get the module size of the game, and I do it successfully by this code here:

Code:
MODULEINFO modinfo;
GetModuleInformation(GetCurrentProcess(), GetModuleHandle("AVA.exe"), &modinfo, sizeof(MODULEINFO));
return (unsigned long)modinfo.SizeOfImage

(I'm doing it through a DLL as you can see)

The problem is at the start of the game it shows uncorrect value like 0 or some lower number.

I tried to do it like this:

Code:
MODULEINFO modinfo;

do
{
	ModuleSize = (unsigned long)modinfo.SizeOfImage;
	Sleep(2000);
	GetModuleInformation(GetCurrentProcess(), GetModuleHandle(filename), &modinfo, sizeof(MODULEINFO));
} while (ModuleSize != (unsigned long)modinfo.SizeOfImage);
But it doesn't always do the job.

So I come to the conclusion that I need to check if the game is fully loaded, and to do that I decided to do this at first:

Code:
while (FindWindow(NULL, "Alliance of Valiant Arms") == NULL) Sleep(2000);
Well it doesn't work.

Can you help me?
Thanks in advance to all the helpers.

Ho and forgot to say that of course I can put the Sleep function in the code but the loading time varies between computers, and it doesn't seem elegant to me.
Quote Originally Posted by Jabberwock View Post
Hey guys, sorry to bother you again.

The problem is I need to get the module size of the game, and I do it successfully by this code here:

Code:
MODULEINFO modinfo;
GetModuleInformation(GetCurrentProcess(), GetModuleHandle("AVA.exe"), &modinfo, sizeof(MODULEINFO));
return (unsigned long)modinfo.SizeOfImage

(I'm doing it through a DLL as you can see)

The problem is at the start of the game it shows uncorrect value like 0 or some lower number.

I tried to do it like this:

Code:
MODULEINFO modinfo;

do
{
	ModuleSize = (unsigned long)modinfo.SizeOfImage;
	Sleep(2000);
	GetModuleInformation(GetCurrentProcess(), GetModuleHandle(filename), &modinfo, sizeof(MODULEINFO));
} while (ModuleSize != (unsigned long)modinfo.SizeOfImage);
But it doesn't always do the job.

So I come to the conclusion that I need to check if the game is fully loaded, and to do that I decided to do this at first:

Code:
while (FindWindow(NULL, "Alliance of Valiant Arms") == NULL) Sleep(2000);
Well it doesn't work.

Can you help me?
Thanks in advance to all the helpers.

Ho and forgot to say that of course I can put the Sleep function in the code but the loading time varies between computer, and it doesn't seem elegant to me.
GetModuleHandle( NULL ) will always get the main base.

replace GetModuleHandle("AVA.exe") with GetModuleHandle( NULL )

MODULEINFO modinfo;
GetModuleInformation(GetCurrentProcess(), GetModuleHandle( NULL ), &modinfo, sizeof(MODULEINFO));
ModuleSize = (unsigned long)modinfo.SizeOfImage;

Also you should verify if GetModuleInformation was successfull before storing the size.

cheers
I know but someone here said it is not reliable.
Hm always worked for me so far, cant think of a case that it wont work.

Maybe if there is an anticheat detour or somekind of process forking technique i dont see how this can fail.
But anyway, both do the same so I don't see what does it matter. We gone off topic.

So can you answer my first post question?

HMODULE WINAPI GetModuleHandle(
_In_opt_ LPCTSTR lpModuleName
);

If this parameter is NULL, GetModuleHandle returns a handle to the file used to create the calling process (.exe file).
It is reliable.

GetModuleInformation returns 0 when it fails, have you tried just looping a sleep until it returns a success?
i.e

Code:
for(int i = 0; i < 50 && !GetModuleInformation(etc...); i++)
    sleep(100);
That would keep it waiting 5 seconds for it to load up (50 * 100); if it hasn't loaded up within 5 seconds it fails. It doesn't make any sense though why it shouldn't work right away... The MSDN doc also says you should be using K32GetModuleInformation
I think this is a good way to do this with loaderlock safety, but you must inject before the process reaches the EP it can be done with createprocess + CREATE_SUSPENDED or by modifing the exe adding your dll to the import table.

You will also need detours 2.0 or above for this or you can make own functions for what you may be missing.

Code:
VOID myPreExecute( )
{
	try
	{
		PIMAGE_DOS_HEADER DosHeader = ( PIMAGE_DOS_HEADER )GetModuleHandle( NULL );

		if( DosHeader == NULL )
			throw "myPreExecute::MZ HEADER NOT PRESENT";

		if( DosHeader->e_magic != IMAGE_DOS_SIGNATURE )
			throw "myPreExecute::NOT VALID DOS IMAGE";

		PIMAGE_NT_HEADERS NtHeader = ( PIMAGE_NT_HEADERS )( ( PBYTE )DosHeader + DosHeader->e_lfanew );

		if( NtHeader->Signature != IMAGE_NT_SIGNATURE || NtHeader->FileHeader.SizeOfOptionalHeader == NULL )
			throw "myPreExecute::NOT VALID WIN32 IMAGE";

		DWORD ModuleSize = NtHeader->OptionalHeader.SizeOfImage;//This is basically what GetModuleInformation is doing...

		//MAGIC HERE
	}
	catch ( LPCSTR Error )//CASE SOMETHING FAILS WE WILL JUMP HERE, PRINT THE ERROR AND PREVENT FURTHER EXECUTION
	{
		MessageBoxA( NULL, Error, NULL, MB_OK );
	}
}

//Redirect the process EntryPoint( WinMain, Start, CRTStartup, CustomEP, PackerEP, Whatever ) to our PreExecute function.
PBYTE ( WINAPI* pEntryPoint )( VOID ) = NULL;
__declspec( naked ) PBYTE WINAPI myEntryPoint( )
{
	__asm
	{
		pushad;
		call myPreExecute;
		popad;
		jmp pEntryPoint;
		ret;
	}
}

BOOL APIENTRY DllMain(_In_ HANDLE _HDllHandle, _In_ DWORD _Reason, _In_opt_ LPVOID _Reserved )
{
	UNREFERENCED_PARAMETER( _HDllHandle );
	UNREFERENCED_PARAMETER( _Reserved );

	if( _Reason == DLL_PROCESS_ATTACH )
	{
		//Lets use the Main EntryPoint to set hooks and other shit so not cause loader lock
		if( ( pEntryPoint = ( PBYTE ( WINAPI* )( VOID ) )DetourGetEntryPoint( NULL ) ) == NULL )
			return FALSE;

		if( FAILED( DetourTransactionBegin( ) ) )
			return FALSE;

		if( FAILED( DetourUpdateThread( GetCurrentThread( ) ) ) )
			return FALSE;

		if( FAILED( DetourAttach( &( PVOID& )pEntryPoint, myEntryPoint ) ) )
			return FALSE;

		if( FAILED( DetourTransactionCommit( ) ) )
			return FALSE;
	}
	return TRUE;
}
For random runtime injection Jetamay sugestion will work just fine.
Guys thank you very much!

Look what happened to me: I tried to do what Jetamay said, at first it didn't work. Then me depressed, changed GetModuleHandle("AVA.exe") to GetModuleHandle(NULL) not that is will make a difference, right? Then an error occurred in the compiler saying that my function doesn't take 0 arguments, I thought this was weird, tried reopening the VS C++ and still no use. So I want to the project files and it turned out that the file I was using was still there, an older file which I include it to the project(Although I update the real one), I removed it and hoops! All is good.

Thanks.

BTW, when I write:

Code:
BOOL success = false;

do
{
	success = GetModuleInformation(GetCurrentProcess(), GetModuleHandle(NULL), &modinfo, sizeof(MODULEINFO));
	ModuleSize = (unsigned long)modinfo.SizeOfImage;
	Sleep(2000);//Not to overload the CPU
} while (success == false);
It's fine, but when I change BOOL success = false; to bool success = false; it gives me:

warning C4800: 'BOOL' : forcing value to bool 'true' or 'false' (performance warning)

What's the difference? I thought they are the same. I prefer to write bool cause it's colored in VS...

I'll just go with this:

Code:
MODULEINFO modinfo;
int success;

do
{
	success = GetModuleInformation(GetCurrentProcess(), GetModuleHandle(NULL), &modinfo, sizeof(MODULEINFO));
	ModuleSize = (unsigned long)modinfo.SizeOfImage;
	Sleep(2000);//Not to overload the CPU
} while (success == NULL);
Color is important to me.
Quote Originally Posted by Jabberwock View Post
Guys thank you very much!

Look what happened to me: I tried to do what Jetamay said, at first it didn't work. Then me depressed, changed GetModuleHandle("AVA.exe") to GetModuleHandle(NULL) not that is will make a difference, right? Then an error occurred in the compiler saying that my function doesn't take 0 arguments, I thought this was weird, tried reopening the VS C++ and still no use. So I want to the project files and it turned out that the file I was using was still there, an older file which I include it to the project(Although I update the real one), I removed it and hoops! All is good.

Thanks.

BTW, when I write:

Code:
BOOL success = false;

do
{
	success = GetModuleInformation(GetCurrentProcess(), GetModuleHandle(NULL), &modinfo, sizeof(MODULEINFO));
	ModuleSize = (unsigned long)modinfo.SizeOfImage;
	Sleep(2000);//Not to overload the CPU
} while (success == false);
It's fine, but when I change BOOL success = false; to bool success = false; it gives me:

warning C4800: 'BOOL' : forcing value to bool 'true' or 'false' (performance warning)

What's the difference? I thought they are the same. I prefer to write bool cause it's colored in VS...
MSDN:
Compiler Warning (level 3) C4800 (C++)

This warning is generated when a value that is not bool is assigned or coerced into type bool. Typically, this message is caused by assigning int variables to bool variables where the int variable contains only values true and false, and could be redeclared as type bool. If you cannot rewrite the expression to use type bool, then you can add "!=0" to the expression, which gives the expression type bool. Casting the expression to type bool will not disable the warning, which is by design.
Basically, GetModuleInformation returns an integer and you are casting it to a bool. Practically speaking it doesn't make a difference, but you should just do something like what I posted, you can remove the timeout though if it makes it easier to understand (if you're ever writing graded\monitored code, always have a timeout though, because without one you introduce the risk of your application hanging):

Code:
while(!GetModuleInformation(GetCurrentProcess(), GetModuleHandle(NULL), &modinfo, sizeof(MODULEINFO)))
	Sleep(2000);

ModuleSize = modinfo.SizeofImage;
Finally, just a tip, most programmers hate do-while loops so you're better off avoiding them if you can.
Quote Originally Posted by radnomguywfq3 View Post
most programmers hate do-while loops so you're better off avoiding them if you can.
Why? they are useful to me.
But you are right, I can avoid them.
Nah, you shouldn't limit yourself. Just use do while loops if you find them useful. Code is not there to look pretty, readable yes, but not pretty. Code only serves one purpose: translating concepts, ideas and logic into computer instructions, and don't let anyone tell you otherwise
I didn't mean to suggest that you shouldn't ever use a do-while loop, but 99% of the time it isn't applied correctly (i.e. OP would've had much cleaner code with a while loop.) And, the fact that it is contravercial amongst programmers is usually enough for me to avoid them. Ofc, there are situations where it makes sense to apply the do-while loop, but more often then not using a while or for makes the code much cleaner.
Posts 112 of 12 · Page 1 of 1

Post a Reply

Similar Threads

Tags for this Thread

None

Need help?