From cf073c8ad43f1f918726062b1e17edd0fe7efe60 Mon Sep 17 00:00:00 2001 From: Andrew Nguyen Date: Tue, 5 Jul 2011 07:19:26 -0500 Subject: [PATCH] dinput8: Improve the behavior of DirectInput8Create. --- dlls/dinput/dinput_main.c | 27 ++++--- dlls/dinput8/dinput8_main.c | 62 +++++++++++----- dlls/dinput8/tests/Makefile.in | 5 +- dlls/dinput8/tests/device.c | 1 - dlls/dinput8/tests/dinput.c | 128 +++++++++++++++++++++++++++++++++ 5 files changed, 193 insertions(+), 30 deletions(-) create mode 100644 dlls/dinput8/tests/dinput.c diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c index 5e7ec6d3736..7b468393379 100644 --- a/dlls/dinput/dinput_main.c +++ b/dlls/dinput/dinput_main.c @@ -554,8 +554,7 @@ static HRESULT WINAPI IDirectInputAImpl_Initialize(LPDIRECTINPUT7A iface, HINSTA return DIERR_INVALIDPARAM; else if (version == 0) return DIERR_NOTINITIALIZED; - /* We need to accept version 8, even though native rejects it. */ - else if (version > DIRECTINPUT_VERSION_700 && version != DIRECTINPUT_VERSION) + else if (version > DIRECTINPUT_VERSION_700) return DIERR_OLDDIRECTINPUTVERSION; else if (version != DIRECTINPUT_VERSION_300 && version != DIRECTINPUT_VERSION_500 && version != DIRECTINPUT_VERSION_50A && version != DIRECTINPUT_VERSION_5B2 && @@ -801,16 +800,28 @@ static HRESULT WINAPI IDirectInput8WImpl_RunControlPanel(LPDIRECTINPUT8W iface, return IDirectInputAImpl_RunControlPanel( &This->IDirectInput7A_iface, hwndOwner, dwFlags ); } -static HRESULT WINAPI IDirectInput8AImpl_Initialize(LPDIRECTINPUT8A iface, HINSTANCE hinst, DWORD x) +static HRESULT WINAPI IDirectInput8AImpl_Initialize(LPDIRECTINPUT8A iface, HINSTANCE hinst, DWORD version) { IDirectInputImpl *This = impl_from_IDirectInput8A( iface ); - return IDirectInputAImpl_Initialize( &This->IDirectInput7A_iface, hinst, x ); + + TRACE("(%p)->(%p, 0x%04x)\n", iface, hinst, version); + + if (!hinst) + return DIERR_INVALIDPARAM; + else if (version == 0) + return DIERR_NOTINITIALIZED; + else if (version < DIRECTINPUT_VERSION) + return DIERR_BETADIRECTINPUTVERSION; + else if (version > DIRECTINPUT_VERSION) + return DIERR_OLDDIRECTINPUTVERSION; + + return initialize_directinput_instance(This, version); } -static HRESULT WINAPI IDirectInput8WImpl_Initialize(LPDIRECTINPUT8W iface, HINSTANCE hinst, DWORD x) +static HRESULT WINAPI IDirectInput8WImpl_Initialize(LPDIRECTINPUT8W iface, HINSTANCE hinst, DWORD version) { IDirectInputImpl *This = impl_from_IDirectInput8W( iface ); - return IDirectInputAImpl_Initialize( &This->IDirectInput7A_iface, hinst, x ); + return IDirectInput8AImpl_Initialize( &This->IDirectInput8A_iface, hinst, version ); } static HRESULT WINAPI IDirectInput8AImpl_FindDevice(LPDIRECTINPUT8A iface, REFGUID rguid, LPCSTR pszName, LPGUID pguidInstance) @@ -1048,9 +1059,7 @@ static HRESULT WINAPI DICF_CreateInstance( IsEqualGUID( &IID_IDirectInput2A, riid ) || IsEqualGUID( &IID_IDirectInput2W, riid ) || IsEqualGUID( &IID_IDirectInput7A, riid ) || - IsEqualGUID( &IID_IDirectInput7W, riid ) || - IsEqualGUID( &IID_IDirectInput8A, riid ) || - IsEqualGUID( &IID_IDirectInput8W, riid ) ) { + IsEqualGUID( &IID_IDirectInput7W, riid ) ) { return create_directinput_instance(riid, ppobj, NULL); } diff --git a/dlls/dinput8/dinput8_main.c b/dlls/dinput8/dinput8_main.c index dcc1d3efb87..661e01adc81 100644 --- a/dlls/dinput8/dinput8_main.c +++ b/dlls/dinput8/dinput8_main.c @@ -55,38 +55,64 @@ static void UnlockModule(void) * DirectInput8Create (DINPUT8.@) */ HRESULT WINAPI DECLSPEC_HOTPATCH DirectInput8Create(HINSTANCE hinst, DWORD dwVersion, REFIID riid, LPVOID *ppDI, LPUNKNOWN punkOuter) { + IDirectInputA *pDI; HRESULT hr, hrCo; TRACE("hInst (%p), dwVersion: %d, riid (%s), punkOuter (%p))\n", hinst, dwVersion, debugstr_guid(riid), punkOuter); - /* The specified version needs to be dinput8 (0x800) or higher */ - if(dwVersion < 0x800) - return DIERR_OLDDIRECTINPUTVERSION; + if (!ppDI) + return E_POINTER; - if( !(IsEqualGUID(&IID_IDirectInput8A, riid) || IsEqualGUID(&IID_IDirectInput8W, riid) || IsEqualGUID(&IID_IUnknown, riid)) ) - return DIERR_INVALIDPARAM; - - hrCo = CoInitialize(NULL); - - hr = CoCreateInstance( &CLSID_DirectInput8, punkOuter, CLSCTX_INPROC_SERVER, riid, ppDI); - if(FAILED(hr)) { - ERR("CoCreateInstance failed with hr = %d\n", hr); - return DIERR_INVALIDPARAM; + if (!IsEqualGUID(&IID_IDirectInput8A, riid) && + !IsEqualGUID(&IID_IDirectInput8W, riid) && + !IsEqualGUID(&IID_IUnknown, riid)) + { + *ppDI = NULL; + return DIERR_NOINTERFACE; } - /* ensure balance of calls */ - if(hrCo == S_OK || hrCo == S_FALSE) + hrCo = CoInitialize(NULL); + + hr = CoCreateInstance(&CLSID_DirectInput, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectInputA, (void **)&pDI); + + /* Ensure balance of calls. */ + if (SUCCEEDED(hrCo)) CoUninitialize(); + if (FAILED(hr)) { + ERR("CoCreateInstance failed with hr = 0x%08x\n", hr); + return hr; + } + + hr = IDirectInput_QueryInterface(pDI, riid, ppDI); + IDirectInput_Release(pDI); + + if (FAILED(hr)) + return hr; + /* When aggregation is used (punkOuter!=NULL) the application needs to manually call Initialize. */ if(punkOuter == NULL && IsEqualGUID(&IID_IDirectInput8A, riid)) { - LPDIRECTINPUTA DI = *ppDI; - IDirectInput8_Initialize(DI, hinst, dwVersion); + IDirectInput8A *DI = *ppDI; + + hr = IDirectInput8_Initialize(DI, hinst, dwVersion); + if (FAILED(hr)) + { + IDirectInput8_Release(DI); + *ppDI = NULL; + return hr; + } } if(punkOuter == NULL && IsEqualGUID(&IID_IDirectInput8W, riid)) { - LPDIRECTINPUTW DI = *ppDI; - IDirectInput8_Initialize(DI, hinst, dwVersion); + IDirectInput8W *DI = *ppDI; + + hr = IDirectInput8_Initialize(DI, hinst, dwVersion); + if (FAILED(hr)) + { + IDirectInput8_Release(DI); + *ppDI = NULL; + return hr; + } } return S_OK; diff --git a/dlls/dinput8/tests/Makefile.in b/dlls/dinput8/tests/Makefile.in index 604be6adf06..7584858099b 100644 --- a/dlls/dinput8/tests/Makefile.in +++ b/dlls/dinput8/tests/Makefile.in @@ -1,7 +1,8 @@ TESTDLL = dinput8.dll -IMPORTS = dinput ole32 user32 +IMPORTS = dinput8 ole32 user32 C_SRCS = \ - device.c + device.c \ + dinput.c @MAKE_TEST_RULES@ diff --git a/dlls/dinput8/tests/device.c b/dlls/dinput8/tests/device.c index 84a499fe9d1..3d35632da30 100644 --- a/dlls/dinput8/tests/device.c +++ b/dlls/dinput8/tests/device.c @@ -24,7 +24,6 @@ #include "wine/test.h" #include "windef.h" -#include "initguid.h" #include "dinput.h" struct enum_data { diff --git a/dlls/dinput8/tests/dinput.c b/dlls/dinput8/tests/dinput.c new file mode 100644 index 00000000000..20056a0feaa --- /dev/null +++ b/dlls/dinput8/tests/dinput.c @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2011 Andrew Nguyen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define DIRECTINPUT_VERSION 0x0800 + +#define COBJMACROS +#include +#include +#include + +#include "wine/test.h" + +HINSTANCE hInstance; + +static void test_DirectInput8Create(void) +{ + static const struct + { + BOOL hinst; + DWORD dwVersion; + REFIID riid; + BOOL ppdi; + HRESULT expected_hr; + } invalid_param_list[] = + { + {FALSE, 0, &IID_IDirectInputA, FALSE, E_POINTER}, + {FALSE, 0, &IID_IDirectInputA, TRUE, DIERR_NOINTERFACE}, + {FALSE, 0, &IID_IDirectInput8A, FALSE, E_POINTER}, + {FALSE, 0, &IID_IDirectInput8A, TRUE, DIERR_INVALIDPARAM}, + {FALSE, DIRECTINPUT_VERSION, &IID_IDirectInputA, FALSE, E_POINTER}, + {FALSE, DIRECTINPUT_VERSION, &IID_IDirectInputA, TRUE, DIERR_NOINTERFACE}, + {FALSE, DIRECTINPUT_VERSION, &IID_IDirectInput8A, FALSE, E_POINTER}, + {FALSE, DIRECTINPUT_VERSION, &IID_IDirectInput8A, TRUE, DIERR_INVALIDPARAM}, + {FALSE, DIRECTINPUT_VERSION - 1, &IID_IDirectInputA, FALSE, E_POINTER}, + {FALSE, DIRECTINPUT_VERSION - 1, &IID_IDirectInputA, TRUE, DIERR_NOINTERFACE}, + {FALSE, DIRECTINPUT_VERSION - 1, &IID_IDirectInput8A, FALSE, E_POINTER}, + {FALSE, DIRECTINPUT_VERSION - 1, &IID_IDirectInput8A, TRUE, DIERR_INVALIDPARAM}, + {FALSE, DIRECTINPUT_VERSION + 1, &IID_IDirectInputA, FALSE, E_POINTER}, + {FALSE, DIRECTINPUT_VERSION + 1, &IID_IDirectInputA, TRUE, DIERR_NOINTERFACE}, + {FALSE, DIRECTINPUT_VERSION + 1, &IID_IDirectInput8A, FALSE, E_POINTER}, + {FALSE, DIRECTINPUT_VERSION + 1, &IID_IDirectInput8A, TRUE, DIERR_INVALIDPARAM}, + {TRUE, 0, &IID_IDirectInputA, FALSE, E_POINTER}, + {TRUE, 0, &IID_IDirectInputA, TRUE, DIERR_NOINTERFACE}, + {TRUE, 0, &IID_IDirectInput8A, FALSE, E_POINTER}, + {TRUE, 0, &IID_IDirectInput8A, TRUE, DIERR_NOTINITIALIZED}, + {TRUE, DIRECTINPUT_VERSION, &IID_IDirectInputA, FALSE, E_POINTER}, + {TRUE, DIRECTINPUT_VERSION, &IID_IDirectInputA, TRUE, DIERR_NOINTERFACE}, + {TRUE, DIRECTINPUT_VERSION, &IID_IDirectInput8A, FALSE, E_POINTER}, + {TRUE, DIRECTINPUT_VERSION - 1, &IID_IDirectInputA, FALSE, E_POINTER}, + {TRUE, DIRECTINPUT_VERSION - 1, &IID_IDirectInputA, TRUE, DIERR_NOINTERFACE}, + {TRUE, DIRECTINPUT_VERSION - 1, &IID_IDirectInput8A, FALSE, E_POINTER}, + {TRUE, DIRECTINPUT_VERSION - 1, &IID_IDirectInput8A, TRUE, DIERR_BETADIRECTINPUTVERSION}, + {TRUE, DIRECTINPUT_VERSION + 1, &IID_IDirectInputA, FALSE, E_POINTER}, + {TRUE, DIRECTINPUT_VERSION + 1, &IID_IDirectInputA, TRUE, DIERR_NOINTERFACE}, + {TRUE, DIRECTINPUT_VERSION + 1, &IID_IDirectInput8A, FALSE, E_POINTER}, + {TRUE, DIRECTINPUT_VERSION + 1, &IID_IDirectInput8A, TRUE, DIERR_OLDDIRECTINPUTVERSION}, + }; + + static const REFIID no_interface_list[] = {&IID_IDirectInputA, &IID_IDirectInputW, + &IID_IDirectInput2A, &IID_IDirectInput2W, + &IID_IDirectInput7A, &IID_IDirectInput7W, + &IID_IDirectInputDeviceA, &IID_IDirectInputDeviceW, + &IID_IDirectInputDevice2A, &IID_IDirectInputDevice2W, + &IID_IDirectInputDevice7A, &IID_IDirectInputDevice7W, + &IID_IDirectInputDevice8A, &IID_IDirectInputDevice8W, + &IID_IDirectInputEffect}; + + static const REFIID iid_list[] = {&IID_IUnknown, &IID_IDirectInput8A, &IID_IDirectInput8W}; + + int i; + IUnknown *pUnk; + HRESULT hr; + + for (i = 0; i < sizeof(invalid_param_list)/sizeof(invalid_param_list[0]); i++) + { + if (invalid_param_list[i].ppdi) pUnk = (void *)0xdeadbeef; + hr = DirectInput8Create(invalid_param_list[i].hinst ? hInstance : NULL, + invalid_param_list[i].dwVersion, + invalid_param_list[i].riid, + invalid_param_list[i].ppdi ? (void **)&pUnk : NULL, + NULL); + ok(hr == invalid_param_list[i].expected_hr, "[%d] DirectInput8Create returned 0x%08x\n", i, hr); + if (invalid_param_list[i].ppdi) + ok(pUnk == NULL, "[%d] Output interface pointer is %p\n", i, pUnk); + } + + for (i = 0; i < sizeof(no_interface_list)/sizeof(no_interface_list[0]); i++) + { + pUnk = (void *)0xdeadbeef; + hr = DirectInput8Create(hInstance, DIRECTINPUT_VERSION, no_interface_list[i], (void **)&pUnk, NULL); + ok(hr == DIERR_NOINTERFACE, "[%d] DirectInput8Create returned 0x%08x\n", i, hr); + ok(pUnk == NULL, "[%d] Output interface pointer is %p\n", i, pUnk); + } + + for (i = 0; i < sizeof(iid_list)/sizeof(iid_list[0]); i++) + { + pUnk = NULL; + hr = DirectInput8Create(hInstance, DIRECTINPUT_VERSION, iid_list[i], (void **)&pUnk, NULL); + ok(hr == DI_OK, "[%d] DirectInput8Create returned 0x%08x\n", i, hr); + ok(pUnk != NULL, "[%d] Output interface pointer is NULL\n", i); + if (pUnk) + IUnknown_Release(pUnk); + } +} + +START_TEST(dinput) +{ + hInstance = GetModuleHandleA(NULL); + + CoInitialize(NULL); + test_DirectInput8Create(); + CoUninitialize(); +}