Commit c126b21a authored by Andrew Nguyen's avatar Andrew Nguyen Committed by Alexandre Julliard

dinput: Extract the DirectInput instance creation and initialization in…

dinput: Extract the DirectInput instance creation and initialization in DirectInputCreateEx to separate functions.
parent e5f73425
......@@ -115,14 +115,42 @@ static BOOL check_hook_thread(void);
static CRITICAL_SECTION dinput_hook_crit;
static struct list direct_input_list = LIST_INIT( direct_input_list );
static HRESULT initialize_directinput_instance(IDirectInputImpl *This, DWORD dwVersion);
static void uninitialize_directinput_instance(IDirectInputImpl *This);
static HRESULT create_directinput_instance(REFIID riid, LPVOID *ppDI, IDirectInputImpl **out)
{
IDirectInputImpl *This = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirectInputImpl) );
HRESULT hr;
if (!This)
return E_OUTOFMEMORY;
This->IDirectInput7A_iface.lpVtbl = &ddi7avt;
This->IDirectInput7W_iface.lpVtbl = &ddi7wvt;
This->IDirectInput8A_iface.lpVtbl = &ddi8avt;
This->IDirectInput8W_iface.lpVtbl = &ddi8wvt;
hr = IDirectInput_QueryInterface( &This->IDirectInput7A_iface, riid, ppDI );
if (FAILED(hr))
{
HeapFree( GetProcessHeap(), 0, This );
return hr;
}
if (out) *out = This;
return DI_OK;
}
/******************************************************************************
* DirectInputCreateEx (DINPUT.@)
*/
HRESULT WINAPI DirectInputCreateEx(
HINSTANCE hinst, DWORD dwVersion, REFIID riid, LPVOID *ppDI,
LPUNKNOWN punkOuter)
LPUNKNOWN punkOuter)
{
IDirectInputImpl* This;
IDirectInputImpl *This;
HRESULT hr;
TRACE("(%p,%04x,%s,%p,%p)\n", hinst, dwVersion, debugstr_guid(riid), ppDI, punkOuter);
......@@ -136,37 +164,21 @@ HRESULT WINAPI DirectInputCreateEx(
IsEqualGUID( &IID_IDirectInput8A, riid ) ||
IsEqualGUID( &IID_IDirectInput8W, riid ))
{
if (!(This = HeapAlloc( GetProcessHeap(), 0, sizeof(IDirectInputImpl) )))
return DIERR_OUTOFMEMORY;
hr = create_directinput_instance(riid, ppDI, &This);
if (FAILED(hr))
return hr;
}
else
return DIERR_OLDDIRECTINPUTVERSION;
This->IDirectInput7A_iface.lpVtbl = &ddi7avt;
This->IDirectInput7W_iface.lpVtbl = &ddi7wvt;
This->IDirectInput8A_iface.lpVtbl = &ddi8avt;
This->IDirectInput8W_iface.lpVtbl = &ddi8wvt;
This->ref = 0;
This->dwVersion = dwVersion;
This->evsequence = 1;
InitializeCriticalSection(&This->crit);
This->crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IDirectInputImpl*->crit");
list_init( &This->devices_list );
/* Add self to the list of the IDirectInputs */
EnterCriticalSection( &dinput_hook_crit );
list_add_head( &direct_input_list, &This->entry );
LeaveCriticalSection( &dinput_hook_crit );
if (!check_hook_thread())
hr = IDirectInput_Initialize( &This->IDirectInput7A_iface, hinst, dwVersion );
if (FAILED(hr))
{
IUnknown_Release( &This->IDirectInput7A_iface );
return DIERR_GENERIC;
IDirectInput_Release( &This->IDirectInput7A_iface );
*ppDI = NULL;
return hr;
}
IDirectInput_QueryInterface( &This->IDirectInput7A_iface, riid, ppDI );
return DI_OK;
}
......@@ -328,6 +340,9 @@ static HRESULT WINAPI IDirectInputAImpl_EnumDevices(
if (!lpCallback)
return DIERR_INVALIDPARAM;
if (!This->initialized)
return DIERR_NOTINITIALIZED;
for (i = 0; i < NB_DINPUT_DEVICES; i++) {
if (!dinput_devices[i]->enum_deviceA) continue;
for (j = 0, r = -1; r != 0; j++) {
......@@ -362,6 +377,9 @@ static HRESULT WINAPI IDirectInputWImpl_EnumDevices(
if (!lpCallback)
return DIERR_INVALIDPARAM;
if (!This->initialized)
return DIERR_NOTINITIALIZED;
for (i = 0; i < NB_DINPUT_DEVICES; i++) {
if (!dinput_devices[i]->enum_deviceW) continue;
for (j = 0, r = -1; r != 0; j++) {
......@@ -399,20 +417,13 @@ static ULONG WINAPI IDirectInputAImpl_Release(LPDIRECTINPUT7A iface)
TRACE( "(%p) releasing from %d\n", This, ref + 1 );
if (ref) return ref;
/* Remove self from the list of the IDirectInputs */
EnterCriticalSection( &dinput_hook_crit );
list_remove( &This->entry );
LeaveCriticalSection( &dinput_hook_crit );
check_hook_thread();
This->crit.DebugInfo->Spare[0] = 0;
DeleteCriticalSection( &This->crit );
HeapFree( GetProcessHeap(), 0, This );
if (ref == 0)
{
uninitialize_directinput_instance( This );
HeapFree( GetProcessHeap(), 0, This );
}
return 0;
return ref;
}
static ULONG WINAPI IDirectInputWImpl_Release(LPDIRECTINPUT7W iface)
......@@ -478,6 +489,53 @@ static HRESULT WINAPI IDirectInputWImpl_QueryInterface(LPDIRECTINPUT7W iface, RE
return IDirectInputAImpl_QueryInterface( &This->IDirectInput7A_iface, riid, ppobj );
}
static HRESULT initialize_directinput_instance(IDirectInputImpl *This, DWORD dwVersion)
{
if (!This->initialized)
{
This->dwVersion = dwVersion;
This->evsequence = 1;
InitializeCriticalSection( &This->crit );
This->crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IDirectInputImpl*->crit");
list_init( &This->devices_list );
/* Add self to the list of the IDirectInputs */
EnterCriticalSection( &dinput_hook_crit );
list_add_head( &direct_input_list, &This->entry );
LeaveCriticalSection( &dinput_hook_crit );
This->initialized = TRUE;
if (!check_hook_thread())
{
uninitialize_directinput_instance( This );
return DIERR_GENERIC;
}
}
return DI_OK;
}
static void uninitialize_directinput_instance(IDirectInputImpl *This)
{
if (This->initialized)
{
/* Remove self from the list of the IDirectInputs */
EnterCriticalSection( &dinput_hook_crit );
list_remove( &This->entry );
LeaveCriticalSection( &dinput_hook_crit );
check_hook_thread();
This->crit.DebugInfo->Spare[0] = 0;
DeleteCriticalSection( &This->crit );
This->initialized = FALSE;
}
}
enum directinput_versions
{
DIRECTINPUT_VERSION_300 = 0x0300,
......@@ -491,6 +549,8 @@ enum directinput_versions
static HRESULT WINAPI IDirectInputAImpl_Initialize(LPDIRECTINPUT7A iface, HINSTANCE hinst, DWORD version)
{
IDirectInputImpl *This = impl_from_IDirectInput7A( iface );
TRACE("(%p)->(%p, 0x%04x)\n", iface, hinst, version);
if (!hinst)
......@@ -506,7 +566,7 @@ static HRESULT WINAPI IDirectInputAImpl_Initialize(LPDIRECTINPUT7A iface, HINSTA
version != DIRECTINPUT_VERSION_700 && version != DIRECTINPUT_VERSION)
return DIERR_BETADIRECTINPUTVERSION;
return DI_OK;
return initialize_directinput_instance(This, version);
}
static HRESULT WINAPI IDirectInputWImpl_Initialize(LPDIRECTINPUT7W iface, HINSTANCE hinst, DWORD x)
......@@ -523,6 +583,9 @@ static HRESULT WINAPI IDirectInputAImpl_GetDeviceStatus(LPDIRECTINPUT7A iface, R
TRACE( "(%p)->(%s)\n", This, debugstr_guid(rguid) );
if (!This->initialized)
return DIERR_NOTINITIALIZED;
hr = IDirectInput_CreateDevice( iface, rguid, &device, NULL );
if (hr != DI_OK) return DI_NOTATTACHED;
......@@ -555,6 +618,9 @@ static HRESULT WINAPI IDirectInputAImpl_RunControlPanel(LPDIRECTINPUT7A iface,
if (dwFlags)
return DIERR_INVALIDPARAM;
if (!This->initialized)
return DIERR_NOTINITIALIZED;
if (!CreateProcessW(NULL, control_exeW, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
return HRESULT_FROM_WIN32(GetLastError());
......@@ -597,6 +663,9 @@ static HRESULT create_device(IDirectInputImpl *This, REFGUID rguid, REFIID riid,
if (!rguid || !pvOut)
return E_POINTER;
if (!This->initialized)
return DIERR_NOTINITIALIZED;
/* Loop on all the devices to see if anyone matches the given GUID */
for (i = 0; i < NB_DINPUT_DEVICES; i++)
{
......@@ -985,8 +1054,7 @@ static HRESULT WINAPI DICF_CreateInstance(
IsEqualGUID( &IID_IDirectInput7W, riid ) ||
IsEqualGUID( &IID_IDirectInput8A, riid ) ||
IsEqualGUID( &IID_IDirectInput8W, riid ) ) {
/* FIXME: reuse already created dinput if present? */
return DirectInputCreateEx(0,0,riid,ppobj,pOuter);
return create_directinput_instance(riid, ppobj, NULL);
}
FIXME("(%p,%p,%s,%p) Interface not found!\n",This,pOuter,debugstr_guid(riid),ppobj);
......
......@@ -37,6 +37,7 @@ struct IDirectInputImpl
LONG ref;
BOOL initialized;
CRITICAL_SECTION crit;
struct list entry; /* entry into list of all IDirectInputs */
......
......@@ -49,6 +49,111 @@ static const DWORD directinput_version_list[] =
DIRECTINPUT_VERSION_700,
};
static BOOL CALLBACK dummy_callback(const DIDEVICEINSTANCEA *instance, void *context)
{
ok(0, "Callback was invoked with parameters (%p, %p)\n", instance, context);
return DIENUM_STOP;
}
static void test_preinitialization(void)
{
static const struct
{
REFGUID rguid;
BOOL pdev;
HRESULT expected_hr;
} create_device_tests[] =
{
{NULL, FALSE, E_POINTER},
{NULL, TRUE, E_POINTER},
{&GUID_Unknown, FALSE, E_POINTER},
{&GUID_Unknown, TRUE, DIERR_NOTINITIALIZED},
{&GUID_SysMouse, FALSE, E_POINTER},
{&GUID_SysMouse, TRUE, DIERR_NOTINITIALIZED},
};
static const struct
{
DWORD dwDevType;
LPDIENUMDEVICESCALLBACKA lpCallback;
DWORD dwFlags;
HRESULT expected_hr;
int todo;
} enum_devices_tests[] =
{
{0, NULL, 0, DIERR_INVALIDPARAM},
{0, NULL, ~0u, DIERR_INVALIDPARAM},
{0, dummy_callback, 0, DIERR_NOTINITIALIZED},
{0, dummy_callback, ~0u, DIERR_INVALIDPARAM, 1},
{0xdeadbeef, NULL, 0, DIERR_INVALIDPARAM},
{0xdeadbeef, NULL, ~0u, DIERR_INVALIDPARAM},
{0xdeadbeef, dummy_callback, 0, DIERR_INVALIDPARAM, 1},
{0xdeadbeef, dummy_callback, ~0u, DIERR_INVALIDPARAM, 1},
};
IDirectInputA *pDI;
HRESULT hr;
int i;
IDirectInputDeviceA *pDID;
hr = CoCreateInstance(&CLSID_DirectInput, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectInputA, (void **)&pDI);
if (FAILED(hr))
{
skip("Failed to instantiate a IDirectInputA instance: 0x%08x\n", hr);
return;
}
for (i = 0; i < sizeof(create_device_tests)/sizeof(create_device_tests[0]); i++)
{
if (create_device_tests[i].pdev) pDID = (void *)0xdeadbeef;
hr = IDirectInput_CreateDevice(pDI, create_device_tests[i].rguid,
create_device_tests[i].pdev ? &pDID : NULL,
NULL);
ok(hr == create_device_tests[i].expected_hr, "[%d] IDirectInput_CreateDevice returned 0x%08x\n", i, hr);
if (create_device_tests[i].pdev)
ok(pDID == NULL, "[%d] Output interface pointer is %p\n", i, pDID);
}
for (i = 0; i < sizeof(enum_devices_tests)/sizeof(enum_devices_tests[0]); i++)
{
hr = IDirectInput_EnumDevices(pDI, enum_devices_tests[i].dwDevType,
enum_devices_tests[i].lpCallback,
NULL,
enum_devices_tests[i].dwFlags);
if (enum_devices_tests[i].todo)
{
todo_wine
ok(hr == enum_devices_tests[i].expected_hr, "[%d] IDirectInput_EnumDevice returned 0x%08x\n", i, hr);
}
else
ok(hr == enum_devices_tests[i].expected_hr, "[%d] IDirectInput_EnumDevice returned 0x%08x\n", i, hr);
}
hr = IDirectInput_GetDeviceStatus(pDI, NULL);
todo_wine
ok(hr == E_POINTER, "IDirectInput_GetDeviceStatus returned 0x%08x\n", hr);
hr = IDirectInput_GetDeviceStatus(pDI, &GUID_Unknown);
ok(hr == DIERR_NOTINITIALIZED, "IDirectInput_GetDeviceStatus returned 0x%08x\n", hr);
hr = IDirectInput_GetDeviceStatus(pDI, &GUID_SysMouse);
ok(hr == DIERR_NOTINITIALIZED, "IDirectInput_GetDeviceStatus returned 0x%08x\n", hr);
hr = IDirectInput_RunControlPanel(pDI, NULL, 0);
ok(hr == DIERR_NOTINITIALIZED, "IDirectInput_RunControlPanel returned 0x%08x\n", hr);
hr = IDirectInput_RunControlPanel(pDI, NULL, ~0u);
ok(hr == DIERR_INVALIDPARAM, "IDirectInput_RunControlPanel returned 0x%08x\n", hr);
hr = IDirectInput_RunControlPanel(pDI, (HWND)0xdeadbeef, 0);
ok(hr == E_HANDLE, "IDirectInput_RunControlPanel returned 0x%08x\n", hr);
hr = IDirectInput_RunControlPanel(pDI, (HWND)0xdeadbeef, ~0u);
ok(hr == E_HANDLE, "IDirectInput_RunControlPanel returned 0x%08x\n", hr);
IDirectInput_Release(pDI);
}
static void test_QueryInterface(void)
{
static const REFIID iid_list[] = {&IID_IUnknown, &IID_IDirectInputA, &IID_IDirectInputW,
......@@ -352,6 +457,7 @@ START_TEST(dinput)
hInstance = GetModuleHandleA(NULL);
CoInitialize(NULL);
test_preinitialization();
test_QueryInterface();
test_CreateDevice();
test_EnumDevices();
......
......@@ -127,7 +127,17 @@ static HRESULT WINAPI DI8CF_CreateInstance(LPCLASSFACTORY iface,LPUNKNOWN pOuter
TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
if( IsEqualGUID( &IID_IDirectInput8A, riid ) || IsEqualGUID( &IID_IDirectInput8W, riid ) || IsEqualGUID( &IID_IUnknown, riid )) {
return DirectInputCreateEx(0, DIRECTINPUT_VERSION, riid, ppobj, pOuter);
IDirectInputA *ppDI;
HRESULT hr;
hr = CoCreateInstance(&CLSID_DirectInput, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectInputA, (void **)&ppDI);
if (FAILED(hr))
return hr;
hr = IDirectInput_QueryInterface(ppDI, riid, ppobj);
IDirectInput_Release(ppDI);
return hr;
}
ERR("(%p,%p,%s,%p) Interface not found!\n",This,pOuter,debugstr_guid(riid),ppobj);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment