2006-12-18 07:22:34 +01:00
/*
* Copyright ( c ) 2006 Vitaliy Margolen
*
* 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 0x0700
# define COBJMACROS
# include <windows.h>
# include "wine/test.h"
# include "windef.h"
# include "dinput.h"
2020-01-12 23:33:24 +01:00
# include <limits.h>
2006-12-18 07:22:34 +01:00
static const DIOBJECTDATAFORMAT obj_data_format [ ] = {
{ & GUID_YAxis , 16 , DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_MAKEINSTANCE ( 1 ) , 0 } ,
{ & GUID_Button , 15 , DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_MAKEINSTANCE ( 3 ) , 0 } ,
{ & GUID_Key , 0 , DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_MAKEINSTANCE ( 16 ) , 0 } ,
{ & GUID_Key , 1 , DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_MAKEINSTANCE ( 17 ) , 0 } ,
{ & GUID_Key , 2 , DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_MAKEINSTANCE ( 18 ) , 0 } ,
{ & GUID_Key , 3 , DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_MAKEINSTANCE ( 19 ) , 0 } ,
{ & GUID_Key , 4 , DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_MAKEINSTANCE ( 20 ) , 0 } ,
{ & GUID_Key , 5 , DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_MAKEINSTANCE ( 21 ) , 0 } ,
{ & GUID_Key , 6 , DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_MAKEINSTANCE ( 22 ) , 0 } ,
{ & GUID_Key , 7 , DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_MAKEINSTANCE ( 23 ) , 0 } ,
{ & GUID_Key , 8 , DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_MAKEINSTANCE ( 24 ) , 0 } ,
{ & GUID_Key , 9 , DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_MAKEINSTANCE ( 25 ) , 0 } ,
{ & GUID_Key , 10 , DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_MAKEINSTANCE ( 26 ) , 0 } ,
{ & GUID_Key , 11 , DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_MAKEINSTANCE ( 27 ) , 0 } ,
{ & GUID_Key , 12 , DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_MAKEINSTANCE ( 28 ) , 0 } ,
{ NULL , 13 , DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_MAKEINSTANCE ( 5 ) , 0 } ,
{ & GUID_Button , 14 , DIDFT_OPTIONAL | DIDFT_BUTTON | DIDFT_MAKEINSTANCE ( 32 ) , 0 }
} ;
static const DIDATAFORMAT data_format = {
sizeof ( DIDATAFORMAT ) ,
sizeof ( DIOBJECTDATAFORMAT ) ,
DIDF_ABSAXIS ,
32 ,
2018-06-07 23:44:39 +02:00
ARRAY_SIZE ( obj_data_format ) ,
2006-12-18 07:22:34 +01:00
( LPDIOBJECTDATAFORMAT ) obj_data_format
} ;
2013-10-29 23:13:02 +01:00
static BOOL CALLBACK enum_callback ( const DIDEVICEOBJECTINSTANCEA * oi , void * info )
2006-12-18 07:22:34 +01:00
{
if ( winetest_debug > 1 )
2007-01-04 19:59:23 +01:00
trace ( " Type:%4x Ofs:%3d Flags:%08x Name:%s \n " ,
oi - > dwType , oi - > dwOfs , oi - > dwFlags , oi - > tszName ) ;
2006-12-18 07:22:34 +01:00
( * ( int * ) info ) + + ;
return DIENUM_CONTINUE ;
}
2013-10-29 23:13:02 +01:00
static BOOL CALLBACK enum_type_callback ( const DIDEVICEOBJECTINSTANCEA * oi , void * info )
2011-07-14 21:24:17 +02:00
{
DWORD expected = * ( DWORD * ) info ;
ok ( expected & DIDFT_GETTYPE ( oi - > dwType ) , " EnumObjects() enumerated wrong type for obj %s, expected: %08x got: %08x \n " , oi - > tszName , expected , oi - > dwType ) ;
return DIENUM_CONTINUE ;
}
2013-10-29 23:13:02 +01:00
static void test_object_info ( IDirectInputDeviceA * device , HWND hwnd )
2006-12-18 07:22:34 +01:00
{
HRESULT hr ;
DIPROPDWORD dp ;
2013-10-29 23:13:02 +01:00
DIDEVICEOBJECTINSTANCEA obj_info ;
2011-07-14 21:24:17 +02:00
DWORD obj_types [ ] = { DIDFT_BUTTON , DIDFT_AXIS , DIDFT_POV } ;
int type_index ;
2011-10-20 15:42:49 +02:00
int cnt1 = 0 ;
DWORD cnt = 0 ;
DIDEVICEOBJECTDATA buffer [ 5 ] ;
2006-12-18 07:22:34 +01:00
hr = IDirectInputDevice_EnumObjects ( device , enum_callback , & cnt , DIDFT_ALL ) ;
2008-07-08 17:49:03 +02:00
ok ( SUCCEEDED ( hr ) , " EnumObjects() failed: %08x \n " , hr ) ;
2006-12-18 07:22:34 +01:00
hr = IDirectInputDevice_SetDataFormat ( device , & data_format ) ;
2008-07-08 17:49:03 +02:00
ok ( SUCCEEDED ( hr ) , " SetDataFormat() failed: %08x \n " , hr ) ;
2006-12-18 07:22:34 +01:00
hr = IDirectInputDevice_EnumObjects ( device , enum_callback , & cnt1 , DIDFT_ALL ) ;
2008-07-08 17:49:03 +02:00
ok ( SUCCEEDED ( hr ) , " EnumObjects() failed: %08x \n " , hr ) ;
2006-12-18 07:22:34 +01:00
if ( 0 ) /* fails for joystick only */
ok ( cnt = = cnt1 , " Enum count changed from %d to %d \n " , cnt , cnt1 ) ;
2011-07-14 21:24:17 +02:00
/* Testing EnumObjects with different types of device objects */
2018-06-07 23:44:39 +02:00
for ( type_index = 0 ; type_index < ARRAY_SIZE ( obj_types ) ; type_index + + )
2011-07-14 21:24:17 +02:00
{
hr = IDirectInputDevice_EnumObjects ( device , enum_type_callback , & obj_types [ type_index ] , obj_types [ type_index ] ) ;
ok ( SUCCEEDED ( hr ) , " EnumObjects() failed: %08x \n " , hr ) ;
}
2011-10-20 15:42:49 +02:00
/* Test buffered mode */
memset ( & dp , 0 , sizeof ( dp ) ) ;
dp . diph . dwSize = sizeof ( DIPROPDWORD ) ;
dp . diph . dwHeaderSize = sizeof ( DIPROPHEADER ) ;
dp . diph . dwHow = DIPH_DEVICE ;
dp . diph . dwObj = 0 ;
2020-01-12 23:33:24 +01:00
dp . dwData = UINT_MAX ;
hr = IDirectInputDevice_GetProperty ( device , DIPROP_BUFFERSIZE , & dp . diph ) ;
ok ( hr = = DI_OK , " Failed: %08x \n " , hr ) ;
ok ( dp . dwData = = 0 , " got %d \n " , dp . dwData ) ;
dp . dwData = UINT_MAX ;
hr = IDirectInputDevice_SetProperty ( device , DIPROP_BUFFERSIZE , ( LPCDIPROPHEADER ) & dp . diph ) ;
ok ( hr = = DI_OK , " SetProperty() failed: %08x \n " , hr ) ;
2011-10-20 15:42:49 +02:00
dp . dwData = 0 ;
2020-01-12 23:33:24 +01:00
hr = IDirectInputDevice_GetProperty ( device , DIPROP_BUFFERSIZE , & dp . diph ) ;
ok ( hr = = DI_OK , " Failed: %08x \n " , hr ) ;
ok ( dp . dwData = = UINT_MAX , " got %d \n " , dp . dwData ) ;
2011-10-20 15:42:49 +02:00
2020-01-12 23:33:24 +01:00
dp . dwData = 0 ;
2011-10-20 15:42:49 +02:00
hr = IDirectInputDevice_SetProperty ( device , DIPROP_BUFFERSIZE , ( LPCDIPROPHEADER ) & dp . diph ) ;
ok ( hr = = DI_OK , " SetProperty() failed: %08x \n " , hr ) ;
cnt = 5 ;
hr = IDirectInputDevice_GetDeviceData ( device , sizeof ( buffer [ 0 ] ) , buffer , & cnt , 0 ) ;
ok ( hr = = DI_OK & & cnt = = 5 , " GetDeviceData() failed: %08x cnt: %d \n " , hr , cnt ) ;
hr = IDirectInputDevice_GetDeviceData ( device , sizeof ( DIDEVICEOBJECTDATA_DX3 ) , buffer , & cnt , 0 ) ;
ok ( hr = = DIERR_NOTBUFFERED , " GetDeviceData() should have failed: %08x \n " , hr ) ;
IDirectInputDevice_Acquire ( device ) ;
hr = IDirectInputDevice_GetDeviceData ( device , sizeof ( DIDEVICEOBJECTDATA_DX3 ) , buffer , & cnt , 0 ) ;
ok ( hr = = DIERR_NOTBUFFERED , " GetDeviceData() should have failed: %08x \n " , hr ) ;
IDirectInputDevice_Unacquire ( device ) ;
dp . dwData = 20 ;
hr = IDirectInputDevice_SetProperty ( device , DIPROP_BUFFERSIZE , ( LPCDIPROPHEADER ) & dp . diph ) ;
ok ( hr = = DI_OK , " SetProperty() failed: %08x \n " , hr ) ;
cnt = 5 ;
hr = IDirectInputDevice_GetDeviceData ( device , sizeof ( buffer [ 0 ] ) , buffer , & cnt , 0 ) ;
ok ( hr = = DI_OK , " GetDeviceData() failed: %08x \n " , hr ) ;
hr = IDirectInputDevice_GetDeviceData ( device , sizeof ( DIDEVICEOBJECTDATA_DX3 ) , buffer , & cnt , 0 ) ;
ok ( hr = = DIERR_NOTACQUIRED , " GetDeviceData() should have failed: %08x \n " , hr ) ;
hr = IDirectInputDevice_Acquire ( device ) ;
ok ( hr = = DI_OK , " Acquire() failed: %08x \n " , hr ) ;
cnt = 1 ;
hr = IDirectInputDevice_GetDeviceData ( device , sizeof ( buffer [ 0 ] ) , buffer , & cnt , 0 ) ;
ok ( hr = = DI_OK , " GetDeviceData() failed: %08x \n " , hr ) ;
hr = IDirectInputDevice_Unacquire ( device ) ;
ok ( hr = = DI_OK , " Unacquire() failed: %08x \n " , hr ) ;
cnt = 1 ;
hr = IDirectInputDevice_GetDeviceData ( device , sizeof ( buffer [ 0 ] ) , buffer , & cnt , 0 ) ;
ok ( hr = = DI_OK , " GetDeviceData() failed: %08x \n " , hr ) ;
2006-12-18 07:22:34 +01:00
/* No need to test devices without axis */
obj_info . dwSize = sizeof ( obj_info ) ;
hr = IDirectInputDevice_GetObjectInfo ( device , & obj_info , 16 , DIPH_BYOFFSET ) ;
if ( SUCCEEDED ( hr ) )
{
/* No device supports per axis relative/absolute mode */
dp . diph . dwHow = DIPH_BYOFFSET ;
dp . diph . dwObj = 16 ;
dp . dwData = DIPROPAXISMODE_ABS ;
hr = IDirectInputDevice_SetProperty ( device , DIPROP_AXISMODE , & dp . diph ) ;
2008-07-08 17:49:03 +02:00
ok ( hr = = DIERR_UNSUPPORTED , " SetProperty() returned: %08x \n " , hr ) ;
2006-12-18 07:22:34 +01:00
dp . diph . dwHow = DIPH_DEVICE ;
hr = IDirectInputDevice_SetProperty ( device , DIPROP_AXISMODE , & dp . diph ) ;
2008-07-08 17:49:03 +02:00
ok ( hr = = DIERR_INVALIDPARAM , " SetProperty() returned: %08x \n " , hr ) ;
2006-12-18 07:22:34 +01:00
dp . diph . dwObj = 0 ;
hr = IDirectInputDevice_SetProperty ( device , DIPROP_AXISMODE , & dp . diph ) ;
2008-07-08 17:49:03 +02:00
ok ( hr = = DI_OK , " SetProperty() failed: %08x \n " , hr ) ;
2006-12-18 07:22:34 +01:00
2007-01-04 10:47:11 +01:00
/* Cannot change mode while acquired */
2006-12-18 07:22:34 +01:00
hr = IDirectInputDevice_Acquire ( device ) ;
2008-07-08 17:49:03 +02:00
ok ( hr = = DI_OK , " Acquire() failed: %08x \n " , hr ) ;
2011-10-16 20:36:43 +02:00
2006-12-18 07:22:34 +01:00
hr = IDirectInputDevice_SetProperty ( device , DIPROP_AXISMODE , & dp . diph ) ;
2008-07-08 17:49:03 +02:00
ok ( hr = = DIERR_ACQUIRED , " SetProperty() returned: %08x \n " , hr ) ;
2011-01-23 20:44:20 +01:00
hr = IDirectInputDevice_Unacquire ( device ) ;
ok ( hr = = DI_OK , " Unacquire() failed: %08x \n " , hr ) ;
2006-12-18 07:22:34 +01:00
}
2020-01-12 23:33:24 +01:00
/* Reset buffer size */
dp . diph . dwSize = sizeof ( DIPROPDWORD ) ;
dp . diph . dwHeaderSize = sizeof ( DIPROPHEADER ) ;
dp . diph . dwHow = DIPH_DEVICE ;
dp . diph . dwObj = 0 ;
dp . dwData = 0 ;
hr = IDirectInputDevice_SetProperty ( device , DIPROP_BUFFERSIZE , ( LPCDIPROPHEADER ) & dp . diph ) ;
ok ( hr = = DI_OK , " SetProperty() failed: %08x \n " , hr ) ;
2006-12-18 07:22:34 +01:00
}
struct enum_data
{
2013-10-29 23:13:02 +01:00
IDirectInputA * pDI ;
2006-12-18 07:22:34 +01:00
HWND hwnd ;
2021-03-23 19:00:36 +01:00
BOOL tested_product_creation ;
2006-12-18 07:22:34 +01:00
} ;
2013-10-29 23:13:02 +01:00
static BOOL CALLBACK enum_devices ( const DIDEVICEINSTANCEA * lpddi , void * pvRef )
2006-12-18 07:22:34 +01:00
{
2009-01-28 10:24:42 +01:00
struct enum_data * data = pvRef ;
2013-10-29 23:13:02 +01:00
IDirectInputDeviceA * device , * obj = NULL ;
2021-03-23 19:00:36 +01:00
DIDEVICEINSTANCEA ddi2 ;
2006-12-18 07:22:34 +01:00
HRESULT hr ;
2008-05-11 21:33:17 +02:00
hr = IDirectInput_GetDeviceStatus ( data - > pDI , & lpddi - > guidInstance ) ;
2008-07-08 17:49:03 +02:00
ok ( hr = = DI_OK , " IDirectInput_GetDeviceStatus() failed: %08x \n " , hr ) ;
2008-05-11 21:33:17 +02:00
if ( hr = = DI_OK )
2006-12-18 07:22:34 +01:00
{
2008-05-11 21:33:17 +02:00
hr = IDirectInput_CreateDevice ( data - > pDI , & lpddi - > guidInstance , & device , NULL ) ;
2008-07-08 17:49:03 +02:00
ok ( SUCCEEDED ( hr ) , " IDirectInput_CreateDevice() failed: %08x \n " , hr ) ;
2011-01-23 20:44:20 +01:00
trace ( " Testing device %p \" %s \" \n " , device , lpddi - > tszInstanceName ) ;
hr = IUnknown_QueryInterface ( device , & IID_IDirectInputDevice2A , ( LPVOID * ) & obj ) ;
2019-10-20 11:32:06 +02:00
ok ( SUCCEEDED ( hr ) , " IUnknown_QueryInterface(IID_IDirectInputDevice2A) failed: %08x \n " , hr ) ;
2011-01-23 20:44:20 +01:00
test_object_info ( obj , data - > hwnd ) ;
2019-10-20 11:32:06 +02:00
IUnknown_Release ( obj ) ;
2011-01-23 20:44:20 +01:00
obj = NULL ;
hr = IUnknown_QueryInterface ( device , & IID_IDirectInputDevice2W , ( LPVOID * ) & obj ) ;
2019-10-20 11:32:06 +02:00
ok ( SUCCEEDED ( hr ) , " IUnknown_QueryInterface(IID_IDirectInputDevice2W) failed: %08x \n " , hr ) ;
2011-01-23 20:44:20 +01:00
test_object_info ( obj , data - > hwnd ) ;
2019-10-20 11:32:06 +02:00
IUnknown_Release ( obj ) ;
2011-01-23 20:44:20 +01:00
2006-12-18 07:22:34 +01:00
IUnknown_Release ( device ) ;
2021-03-23 19:00:36 +01:00
if ( ! IsEqualGUID ( & lpddi - > guidInstance , & lpddi - > guidProduct ) )
{
data - > tested_product_creation = TRUE ;
hr = IDirectInput_CreateDevice ( data - > pDI , & lpddi - > guidProduct , & device , NULL ) ;
ok ( SUCCEEDED ( hr ) , " IDirectInput_CreateDevice() failed: %08x \n " , hr ) ;
ddi2 . dwSize = sizeof ( ddi2 ) ;
hr = IDirectInputDevice_GetDeviceInfo ( device , & ddi2 ) ;
ok ( SUCCEEDED ( hr ) , " IDirectInput_GetDeviceInfo failed: %08x \n " , hr ) ;
ok ( IsEqualGUID ( & lpddi - > guidProduct , & ddi2 . guidProduct ) , " Product GUIDs do not match. Expected %s, got %s \n " , debugstr_guid ( & lpddi - > guidProduct ) , debugstr_guid ( & ddi2 . guidProduct ) ) ;
ok ( IsEqualGUID ( & ddi2 . guidProduct , & ddi2 . guidInstance ) , " Instance GUID should equal product GUID. Expected %s, got %s \n " , debugstr_guid ( & ddi2 . guidProduct ) , debugstr_guid ( & ddi2 . guidInstance ) ) ;
/* we cannot compare guidInstances as we may get a different device */
IUnknown_Release ( device ) ;
}
2006-12-18 07:22:34 +01:00
}
return DIENUM_CONTINUE ;
}
static void device_tests ( void )
{
HRESULT hr ;
2013-10-29 23:13:02 +01:00
IDirectInputA * pDI = NULL , * obj = NULL ;
HINSTANCE hInstance = GetModuleHandleW ( NULL ) ;
2006-12-18 07:22:34 +01:00
HWND hwnd ;
struct enum_data data ;
2011-01-23 20:44:20 +01:00
hr = CoCreateInstance ( & CLSID_DirectInput , 0 , 1 , & IID_IDirectInput2A , ( LPVOID * ) & pDI ) ;
if ( hr = = DIERR_OLDDIRECTINPUTVERSION | | hr = = DIERR_DEVICENOTREG )
2008-03-07 20:26:57 +01:00
{
skip ( " Tests require a newer dinput version \n " ) ;
return ;
}
2013-10-29 23:13:02 +01:00
ok ( SUCCEEDED ( hr ) , " DirectInputCreateA() failed: %08x \n " , hr ) ;
2006-12-18 07:22:34 +01:00
if ( FAILED ( hr ) ) return ;
2011-01-23 20:44:20 +01:00
hr = IDirectInput_Initialize ( pDI , hInstance , DIRECTINPUT_VERSION ) ;
ok ( SUCCEEDED ( hr ) , " Initialize() failed: %08x \n " , hr ) ;
if ( FAILED ( hr ) ) return ;
hr = IUnknown_QueryInterface ( pDI , & IID_IDirectInput2W , ( LPVOID * ) & obj ) ;
ok ( SUCCEEDED ( hr ) , " QueryInterface(IDirectInput7W) failed: %08x \n " , hr ) ;
2013-10-29 23:13:02 +01:00
hwnd = CreateWindowA ( " static " , " Title " , WS_OVERLAPPEDWINDOW , 10 , 10 , 200 , 200 , NULL , NULL ,
NULL , NULL ) ;
2006-12-18 07:22:34 +01:00
ok ( hwnd ! = NULL , " err: %d \n " , GetLastError ( ) ) ;
if ( hwnd )
{
ShowWindow ( hwnd , SW_SHOW ) ;
data . pDI = pDI ;
data . hwnd = hwnd ;
2021-03-23 19:00:36 +01:00
data . tested_product_creation = FALSE ;
2006-12-18 07:22:34 +01:00
hr = IDirectInput_EnumDevices ( pDI , 0 , enum_devices , & data , DIEDFL_ALLDEVICES ) ;
2008-07-08 17:49:03 +02:00
ok ( SUCCEEDED ( hr ) , " IDirectInput_EnumDevices() failed: %08x \n " , hr ) ;
2006-12-18 07:22:34 +01:00
2021-03-23 19:00:36 +01:00
if ( ! data . tested_product_creation ) winetest_skip ( " Device creation using product GUID not tested \n " ) ;
2008-05-11 21:33:17 +02:00
/* If GetDeviceStatus returns DI_OK the device must exist */
hr = IDirectInput_GetDeviceStatus ( pDI , & GUID_Joystick ) ;
if ( hr = = DI_OK )
{
2013-10-29 23:13:02 +01:00
IDirectInputDeviceA * device = NULL ;
2008-05-11 21:33:17 +02:00
hr = IDirectInput_CreateDevice ( pDI , & GUID_Joystick , & device , NULL ) ;
2008-07-08 17:49:03 +02:00
ok ( SUCCEEDED ( hr ) , " IDirectInput_CreateDevice() failed: %08x \n " , hr ) ;
2008-05-11 21:33:17 +02:00
if ( device ) IUnknown_Release ( device ) ;
}
2006-12-18 07:22:34 +01:00
DestroyWindow ( hwnd ) ;
}
2011-01-23 20:44:20 +01:00
if ( obj ) IUnknown_Release ( obj ) ;
2006-12-18 07:22:34 +01:00
if ( pDI ) IUnknown_Release ( pDI ) ;
}
START_TEST ( device )
{
CoInitialize ( NULL ) ;
device_tests ( ) ;
CoUninitialize ( ) ;
}