madCodeHook (with DirectDraw) + wine

Questions about Wine on Linux
Locked
Muzer
Newbie
Newbie
Posts: 3
Joined: Sun Oct 07, 2012 4:23 pm

madCodeHook (with DirectDraw) + wine

Post by Muzer »

Hi all,

[This is a modification of a my from here; the developer of madCodeHook has never used wine so I thought I might have a bit more luck asking here]

There's a game, older versions of which fail in wine (I'm a tester so need to run them for regression testing), and as it has a well-used extension framework, I thought it'd be nicer to make a module that allows it (and a related but non-updated game) to run in wine than for people to have to patch wine itself. It's worth pointing out here and now that it has been clearly stated that wine will not or cannot be changed to support the older versions of this game without breaking other things.

The way to get the game to run is to cause its DirectDraw SetCooperativeLevel calls to provide the desktop window as an argument.

So, armed with not much knowledge about how these things work, and the old evaluation version of madCodeHook, I thought I'd try to get something working.

I developed the whole thing on Windows and after much crazy guessing and getting things wrong, I was eventually pleased to see that it worked! (Performing this change has a few side-effects which I checked for and were, indeed, present when run in Windows). So far, so good. But then I ran it in wine, and it didn't work. I did a little debugging and found that it was hooking DirectDrawCreate fine but when attempting to hook the SetCooperativeLevel interface method, HookCode returned true but the hook function wasn't being called. Further debugging showed that if I called SetCooperativeLevel myself (from the DLL) the hook WOULD work, and that calling things DID have effect so it was definitely the correct pointer (I called SetDisplayMode and noticed a very brief resolution change did, in fact, occur).



So, I'm wondering - is this a wine bug, a wine design issue, some problem with my code or a weird (latent on Windows?) bug in the old madCodeHook? Is there any way I could work around it? Here is my code (with silly debugging stuff left in):

Code: Select all

#include "main.h"
#include <madCHook - dynamic.h>

PVOID GetInterfaceMethod(PVOID intf, DWORD methodIndex)
{
  return *(PVOID*)(*(DWORD*)intf + methodIndex * 4);
}

HRESULT (WINAPI *SCLNext)(void *ptr, HWND hwnd, DWORD dwFlags) = NULL;

HRESULT WINAPI SCLCallback(void *ptr, HWND hwnd, DWORD dwFlags)
{
    printf("The co-operative. Good with Desktops.\n");
    return SCLNext(ptr, GetDesktopWindow(), dwFlags);
}

HRESULT (WINAPI *DDrawCreateNext)(GUID FAR *lpGUID, LPDIRECTDRAW FAR *lplpDD, IUnknown FAR *pUnkOuter);

HRESULT WINAPI DDrawCreateHook(GUID FAR *lpGUID, LPDIRECTDRAW FAR *lplpDD, IUnknown FAR *pUnkOuter)
{
    HRESULT reslt = DDrawCreateNext(lpGUID, lplpDD, pUnkOuter);
    if(SCLNext == NULL)
    {
        printf("Hooking SCL in 3... 2... 1...\n");
        printf("hookcode %i\n",HookCode(GetInterfaceMethod(*lplpDD, 20), (void *)SCLCallback, (PVOID*)&SCLNext));
    }
    return reslt;
}

BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    printf("Hello!\n");
    switch (fdwReason)
    {
        case DLL_PROCESS_ATTACH:
            InitializeMadCHook();
            printf("You're going MAD!\n");
            HookAPI("DDRAW.dll", "DirectDrawCreate", (void *)DDrawCreateHook, (PVOID *) &DDrawCreateNext);

            // attach to process
            // return FALSE to fail DLL load
            break;

        case DLL_PROCESS_DETACH:
            // detach from process
            break;

        case DLL_THREAD_ATTACH:
            // attach to thread
            break;

        case DLL_THREAD_DETACH:
            // detach from thread
            break;
    }
    return TRUE; // succesful
}

and the header in case you need that:

Code: Select all

#ifndef __MAIN_H__
#define __MAIN_H__

#include <iostream>
#include <fstream>
#include <windows.h>
#include <Ddraw.h>

/*  To use this exported function of dll, include this header
 *  in your project.
 */

#ifdef BUILD_DLL
    #define DLL_EXPORT __declspec(dllexport)
#else
    #define DLL_EXPORT __declspec(dllimport)
#endif


#ifdef __cplusplus
extern "C"
{
#endif

DLL_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved);
DLL_EXPORT HRESULT WINAPI DDrawCreateHook(GUID FAR *lpGUID, LPDIRECTDRAW FAR *lplpDD, IUnknown FAR *pUnkOuter);
DLL_EXPORT HRESULT WINAPI SCLCallback(void *ptr, HWND hwnd, DWORD dwFlags);
DLL_EXPORT PVOID GetInterfaceMethod(PVOID intf, DWORD methodIndex);

#ifdef __cplusplus
}
#endif

#endif // __MAIN_H__
User avatar
DanKegel
Moderator
Moderator
Posts: 1164
Joined: Wed May 14, 2008 11:44 am

Re: madCodeHook (with DirectDraw) + wine

Post by DanKegel »

Muzer
Newbie
Newbie
Posts: 3
Joined: Sun Oct 07, 2012 4:23 pm

Re: madCodeHook (with DirectDraw) + wine

Post by Muzer »

Thanks - I'd seen that page before but hadn't scrolled down to the relevant bits ;)

I think I at least vaguely understand that - so could it be the case that the pointer returned by DirectDrawCreate is the "wrong" one for hooking purposes (for whatever reason)? If so, would there be some way to figure out the "correct" one for hooking? Or am I completely barking up the wrong tree?
User avatar
DanKegel
Moderator
Moderator
Posts: 1164
Joined: Wed May 14, 2008 11:44 am

Re: madCodeHook (with DirectDraw) + wine

Post by DanKegel »

I don't suppose there's any way you can rebuild the older versions of the game with the newer madcodehook...
Muzer
Newbie
Newbie
Posts: 3
Joined: Sun Oct 07, 2012 4:23 pm

Re: madCodeHook (with DirectDraw) + wine

Post by Muzer »

Hmm? The game is closed-source, I can't rebuild it (and I assume you mean with the function changed rather than with the newer madcodehook as that doesn't make a lot of sense to me in this context - the game itself doesn't use madcodehook, it's just the way I thought of hooking the function as being the easiest and less irritating for when I'm using different wine installations and don't have to manually patch each one's source).
Locked