Setting both EXCLUSIVE and BACKGROUND flags for keyboard or mouse is invalid and DInput will throw an error when you try that. You might therefore want to check that you're trying to modify the cooperative level only on the device you want to use. The handling of these invalid flags is perhaps different on WinXP which is why LFS crashed for you. If it's any help, I did it like this when I wanted to check for a Logitech G27 in my proxied dinput8.dll. BTW, I found out that calling Beep() from a proxy DLL is a crude but effective way to check that the code reaches a certain place
1) An application has to enumerate the devices first so let's take advantage of that and enumerate them along with it
HRESULT myIDirectInput8::EnumDevices(DWORD a, LPDIENUMDEVICESCALLBACKW b, LPVOID c, DWORD d)
{
m_pIDirectInput8->EnumDevices(a, MyDevEnumCallBack, c, d);
return m_pIDirectInput8->EnumDevices(a, b, c, d);
}
2) Get some interesting info about a device during the enumeration
BOOL CALLBACK myIDirectInput8::MyDevEnumCallBack(const DIDEVICEINSTANCE* inst, VOID* context)
{
UNREFERENCED_PARAMETER(context);
/* Here is where we store the GUIDs of devices that we want to manipulate with later */
extern std::vector<GUID> gl_myG27Instance;
/* Check the device's identity */
if ((inst->guidProduct.Data1 == G27ID) /* || (inst->guidProduct.Data1 == DFPID) */) {
/* Check if we already have this device added */
if (gl_myG27Instance.size() > 20)
return DIENUM_CONTINUE;
for (std::vector<GUID>::const_iterator cit = gl_myG27Instance.begin(); cit != gl_myG27Instance.end(); cit++) {
if (IsEqualCLSID(inst->guidProduct, *cit))
return DIENUM_CONTINUE;
}
gl_myG27Instance.push_back(inst->guidInstance);
}
return DIENUM_CONTINUE;
}
3) OK, now we know the GUIDs that reference the devices we're interested in so let's intercept only those devices */
HRESULT myIDirectInput8::CreateDevice(REFGUID a, LPDIRECTINPUTDEVICE8W *b, LPUNKNOWN c)
{
extern std::vector<GUID> gl_myG27Instance;
std::vector<GUID>::const_iterator cit;
for (cit = gl_myG27Instance.begin(); cit < gl_myG27Instance.end(); cit++) {
if (IsEqualCLSID(a, *cit)) {
/* A G27 (or DFP) found, take control over this device */
// global var
extern myIDirectInputDevice8* gl_pmyIDirectInputDevice8Array[];
LogMessage(L"DI::CreateDevice> Creating DIDevice");
// we intercept this call and provide our own "fake" Device Object
HRESULT hres = m_pIDirectInput8->CreateDevice(a,b,c);
/*
* Check for error
*/
// find free Device slot
int i;
for (i=0; i<MAXNUMBER_DEVICES; i++)
if (gl_pmyIDirectInputDevice8Array[i] == NULL) break;
/*
* Should return an error if i == MAXNUMBER_DEVICES
*/
// Create our own Device object and store it in global pointer
// note: the object will delete itself once Ref count is zero (similar to COM objects)
gl_pmyIDirectInputDevice8Array[i] = new myIDirectInputDevice8(*b, i, *cit);
// store our pointer (the fake one) for returning it to the calling progam
*b = gl_pmyIDirectInputDevice8Array[i];
LPOLESTR guidHash;
HRESULT guidHRes = StringFromCLSID(a, &guidHash);
if (guidHRes == S_OK) {
std::wostringstream oss;
oss << L"DI::CreateDevice> Creating DIDevice, GUID " << guidHash;
LogMessage(oss.str().c_str());
CoTaskMemFree(guidHash);
} else
LogMessage(L"(WARN)DI::CreateDevice> Unable to convert GUID to string.");
if (hres == S_OK)
LogMessage(L"DI::CreateDevice> Device sucessfully created.");
else
LogMessage(L"(WARN)DI::CreateDevice> Unable to create device.");
return(hres);
}
}
/* Not a G27 (or DFP), don't touch this device */
LogMessage(L"DI::CreateDevice> Not a G27, ignoring.");
return m_pIDirectInput8->CreateDevice(a, b, c);
}
The code above is far from brilliant but it seems to have solved the problem in my G27 LEDs hack.