Bruno
Bruno

Reputation: 458

How to call function direct from pointer?

I'm learning how to hook some functions in a gameserver using c++ and I saw a code that call a function directly from a pointer.

Here's the code that I saw :

#define DataRecv ((void(*) (BYTE, PBYTE, DWORD, DWORD,…)) 0x004368E0)

Here's my code:

#define LoadMoveLevel ((void(*) (char *)) 0x0051DF70)

How I can call the function LoadMoveLevel? I tried that :

MessageBoxA(NULL, LoadMoveLevel("teste"), "example", MB_OK);

but get this error : Argument of type void is imcompatible with parameter type LPCSTR

Thanks.

Upvotes: 0

Views: 114

Answers (5)

Potatoswatter
Potatoswatter

Reputation: 137780

First load the interface: #include "MoveCommand.h"

Then call the function by its proper name: gMoveCommand.LoadMoveLevel("teste");

The return value is still an int, not a char*. Please refer to the server documentation to learn about proper usage.

(Seeing something like #define DataRecv would cause me to run away from a project. Do not take any of this muOnline clone as an example of good, or even valid, C++.)

Upvotes: 1

James Adkison
James Adkison

Reputation: 9602

Per the documentation the MessageBoxA function has the following signature:

int WINAPI MessageBox(
_In_opt_ HWND hWnd,
_In_opt_ LPCTSTR lpText,
_In_opt_ LPCTSTR lpCaption,
In UINT uType
);

You can see that the 2nd argument is of type LPCTSTR but you're function returns void. Therefore, you cannot call it in the 2nd parameter because it does not return the required type.

#define LoadMoveLevel ((void(*) (char *)) 0x0051DF70)
// ^^^^ // This is the return type of the function

Note: The 'A' appended to the message box function name means you're using the ANSI version (as opposed the the UNICODE version) and the 2nd argument is actually LPCSTR (i.e., const char*) in your case.

As R Sahu mentions to call it as a parameter the the message box function the return type would need to be changed from void to the appropriate type.

Upvotes: 1

Peter
Peter

Reputation: 36597

You have defined LoadMoveLevel() to be a call via a pointer to a function that returns void. The second argument of MessageBoxA() is a (const) char *. A return of void from a function does not yield any value, so cannot be converted to anything. Hence the error.

What the macro is doing is converting the value to a pointer (to function) and then calling the function. To make it compile, change your macro to either

#define LoadMoveLevel ((LPCSTR (*) (char *)) 0x0051DF70)

or (expanding LPCSTR) to

#define LoadMoveLevel (((char *) (*) (char *)) 0x0051DF70)

Note that what you are doing is extremely dangerous. Converting an arbitrary value to a function pointer in order to call it relies on there ACTUALLY being valid code at that location. Odds are, if you do not understand the syntax (as per your question) you do not know how to ensure that the code at that location corresponds to a function that accepts a char * as an argument, and returns a char *.

Upvotes: 0

Eric Tsui
Eric Tsui

Reputation: 1924

According to definition of MessageBoxA,

int WINAPI MessageBox(
_In_opt_ HWND hWnd,
_In_opt_ LPCTSTR lpText,
_In_opt_ LPCTSTR lpCaption,
_In_ UINT uType);

When you call MessageBoxA(NULL, LoadMoveLevel("teste"), "example", MB_OK);, the 2nd parameter needs a LPCTSTR, but you return void by

#define LoadMoveLevel ((void(*) (char *)) 0x0051DF70)

Upvotes: 1

R Sahu
R Sahu

Reputation: 206567

The second argument of MessageBoxA is of type LPCSTR. The way you have defined LoadMoveLevel, the return value of LoadMoveLevel("teste") is void. That's what the compiler is complaining about.

If the function that lives at the address 0x0051DF70 is supposed to return void indeed, you cannot use LoadMoveLevel. If that function is supposed to return a LPCSTR, then, you have to change LoadMoveLevel to:

#define LoadMoveLevel ((LPCSTR (*) (char *)) 0x0051DF70)

and then, the call

MessageBoxA(NULL, LoadMoveLevel("teste"), "example", MB_OK);

should work.

Upvotes: 0

Related Questions