开发者

Creating a cross-process function pointer

I have a Visual Studio 2008 C++ project for Windows Mobile 6 with two processes. Both of which I would like to have access to the same function which is contained in process1.

That function is Buzz:

struct TEST_STRUCT
{
    int bar;
    WCHAR foo[ 20 ];
};

typedef int( *pfn_Buzz )( TEST_STRUCT* );

int Buzz( TEST_STRUCT* info );

Process1 contains the definition for Buzz and creates a function pointer for it in a memory-mapped file:

int Buzz( TEST_STRUCT* info )
{
    info->bar = 1;
    wsprintf( info->foo, L"Hello!" );
    return 100;
}

int _tmain( int argc, _TCHAR* argv[] )
{
    // create a memory-mapped file shared memory space that can be read by any process
    HANDLE mapping = ::CreateFileMapping( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof( pfn_Buzz ) , NULL );
    LPVOID buzz_addr = ::MapViewOfFile( mapping, FILE_MAP_ALL_ACCESS, 0, 0, sizeof( pfn_Buzz ) );

    // find our process' memory offset
    DWORD offset = ::GetCurrentProcessIndex() + 0x02000000;

    // copy the complete function address to the shared memory space
    buzz_addr = ( LPVOID )( ( DWORD )&Buzz + offset );

    // convert the function address to a string to send to process2.exe
    WCHAR address[ 9 ] = { 0 };
    wsprintf( address, L"%x", ( ( DWORD )buzz_addr ) );

    // start开发者_高级运维 process2.exe and wait for it to finish
    PROCESS_INFORMATION pi = { 0 };
    ::CreateProcess( L"\\test_user.exe", address, NULL, NULL, FALSE, 0, NULL, NULL, NULL, &pi );
    ::WaitForSingleObject( pi.hProcess, INFINITE );

    ::UnmapViewOfFile( buzz_addr );
    ::CloseHandle( mapping );

    return 0;
}

Process2 receives the address for Buzz from Process1, casts it to the pfn_Buzz function pointer, and executes it.

// process2.exe
int _tmain( int argc, _TCHAR* argv[] )
{
    // get the address of the Buzz() function pointer
    WCHAR* wszAddr = argv[ 1 ];
    WCHAR* wszAddrEnd = &argv[ 1 ][ 8 ];
    DWORD address = wcstol( wszAddr, &wszAddrEnd, 16 );
    pfn_Buzz PFNBuzz = ( pfn_Buzz )address;

    // execute buzz
    TEST_STRUCT test = { 0 };
    PFNBuzz( &test );

    return 0;
}

Unfortunately, I get an Illegal Instruction exception in process2 when I try to execute the PFNBuzz function.

Can anybody suggest what I could change to get the functionality I'm after?

Thanks, PaulH


Your problem arises from the fact that Process A (Which starts Process B) have 2 totally different virtual address spaces. You can pass a function pointer to Process A but seeeing as their address spaces are different any pointer you pass will be meaining less to another process. this is one of the huge bonuses of processes.

If you wish to communicate between processes then you will need to use some form of Inter-Process Communication (IPC).

There are several ways of doing IPC under windows. In my opinion the most versatile method is by using sockets. Sockets give you the advantage that you can seperate the machines running Process A and Process B and still get the functionality you want. Equally there is nothing stopping both processes running on the same machine. The flexibility it provides is very useful though.

So assuming you choose a socket based method of IPC then what you are effectively doing is a Remote Procedure Call (RPC).

There are, as you can probably imagine, loads of different ways of doing RPC. You could use DCOM or Corba. Raknet is a third party library that supports RPC. There are numerous other solutions as well. I strongly recommend doing a load of research into the matter. The links and keywords I've provided you with should give you a good starting point :)


You can simply export the function using __declspec(dllexport) and then load it using GetProcAddress() using it's name. If in C++, just remember to extern "C" the declaration to disable name mangling. Consider:

extern "C" int __declspec(dllexport) Buzz( TEST_STRUCT* info ) { ... }
int main ( int, char ** )
{
    pfn_Buzz buzz = GetProcAddress(GetModuleHandle(NULL), "Buzz");
    // ...
}

Then, pass the function name using the IPC method of your choice.


If you want both processes to use the same function, put the function into a DLL and link that DLL to both processes. Each process has its own address space, so an address in one process may not work at all in another process, and even if it "works" it'll be pointing to something completely different.

Although you're taking/passing the offset into the memory mapped region on the parent side, I don't see any matching code to map the same region and add its base to the pointer when you try to access it on the client side.

Visual C++ has a __based pointer type that can simplify this a bit.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜