[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__