dinput: Stub support for DIPROP_FFLOAD device property.
[wine.git] / dlls / dinput8 / tests / hid.c
blobbcff4b598464372d969c31a09656c33bc37bfb6d
1 /*
2 * Copyright 2021 RĂ©mi Bernon for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #define DIRECTINPUT_VERSION 0x0800
21 #include <stdarg.h>
22 #include <stddef.h>
24 #include "ntstatus.h"
25 #define WIN32_NO_STATUS
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winioctl.h"
29 #include "winternl.h"
30 #include "wincrypt.h"
31 #include "winreg.h"
32 #include "winsvc.h"
33 #include "winuser.h"
34 #include "winnls.h"
36 #include "mscat.h"
37 #include "mssip.h"
38 #include "ntsecapi.h"
39 #include "setupapi.h"
40 #include "cfgmgr32.h"
41 #include "newdev.h"
43 #include "objbase.h"
45 #define COBJMACROS
46 #include "wingdi.h"
47 #include "dinput.h"
48 #include "dinputd.h"
50 #include "initguid.h"
51 #include "ddk/wdm.h"
52 #include "ddk/hidclass.h"
53 #include "ddk/hidsdi.h"
54 #include "ddk/hidpi.h"
55 #include "ddk/hidport.h"
56 #include "hidusage.h"
57 #include "devguid.h"
59 #include "wine/test.h"
60 #include "wine/mssign.h"
61 #include "wine/hid.h"
63 #include "driver_hid.h"
65 static HINSTANCE instance;
66 static BOOL localized; /* object names get translated */
68 #define EXPECT_VIDPID MAKELONG( 0x1209, 0x0001 )
69 static const WCHAR expect_vidpid_str[] = L"VID_1209&PID_0001";
70 static const GUID expect_guid_product = {EXPECT_VIDPID,0x0000,0x0000,{0x00,0x00,'P','I','D','V','I','D'}};
71 static const WCHAR expect_path[] = L"\\\\?\\hid#winetest#1&2fafeb0&";
72 static const WCHAR expect_path_end[] = L"&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}";
74 static struct winetest_shared_data *test_data;
75 static HANDLE okfile;
77 static HRESULT (WINAPI *pSignerSign)( SIGNER_SUBJECT_INFO *subject, SIGNER_CERT *cert,
78 SIGNER_SIGNATURE_INFO *signature, SIGNER_PROVIDER_INFO *provider,
79 const WCHAR *timestamp, CRYPT_ATTRIBUTES *attr, void *sip_data );
81 static const WCHAR container_name[] = L"wine_testsign";
83 static const CERT_CONTEXT *testsign_sign( const WCHAR *filename )
85 BYTE encoded_name[100], encoded_key_id[200], public_key_info_buffer[1000];
86 BYTE hash_buffer[16], cert_buffer[1000], provider_nameA[100], serial[16];
87 CERT_PUBLIC_KEY_INFO *public_key_info = (CERT_PUBLIC_KEY_INFO *)public_key_info_buffer;
88 SIGNER_SIGNATURE_INFO signature = {sizeof(SIGNER_SIGNATURE_INFO)};
89 SIGNER_CERT_STORE_INFO store = {sizeof(SIGNER_CERT_STORE_INFO)};
90 SIGNER_ATTR_AUTHCODE authcode = {sizeof(SIGNER_ATTR_AUTHCODE)};
91 SIGNER_SUBJECT_INFO subject = {sizeof(SIGNER_SUBJECT_INFO)};
92 SIGNER_FILE_INFO file = {sizeof(SIGNER_FILE_INFO)};
93 SIGNER_CERT signer = {sizeof(SIGNER_CERT)};
94 CRYPT_KEY_PROV_INFO provider_info = {0};
95 CRYPT_ALGORITHM_IDENTIFIER algid = {0};
96 CERT_AUTHORITY_KEY_ID_INFO key_info;
97 HCERTSTORE root_store, pub_store;
98 CERT_INFO cert_info = {0};
99 WCHAR provider_nameW[100];
100 const CERT_CONTEXT *cert;
101 CERT_EXTENSION extension;
102 DWORD size, index = 0;
103 HCRYPTPROV provider;
104 HCRYPTKEY key;
105 HRESULT hr;
106 BOOL ret;
108 ret = CryptAcquireContextW( &provider, container_name, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET );
109 if (!ret && GetLastError() == NTE_EXISTS)
111 ret = CryptAcquireContextW( &provider, container_name, NULL, PROV_RSA_FULL, CRYPT_DELETEKEYSET );
112 ok( ret, "Failed to delete container, error %#x\n", GetLastError() );
113 ret = CryptAcquireContextW( &provider, container_name, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET );
115 ok( ret, "Failed to create container, error %#x\n", GetLastError() );
117 ret = CryptGenKey( provider, AT_SIGNATURE, CRYPT_EXPORTABLE, &key );
118 ok( ret, "Failed to create key, error %#x\n", GetLastError() );
119 ret = CryptDestroyKey( key );
120 ok( ret, "Failed to destroy key, error %#x\n", GetLastError() );
121 ret = CryptGetUserKey( provider, AT_SIGNATURE, &key );
122 ok( ret, "Failed to get user key, error %#x\n", GetLastError() );
123 ret = CryptDestroyKey( key );
124 ok( ret, "Failed to destroy key, error %#x\n", GetLastError() );
126 size = sizeof(encoded_name);
127 ret = CertStrToNameW( X509_ASN_ENCODING, L"CN=winetest_cert", CERT_X500_NAME_STR, NULL,
128 encoded_name, &size, NULL );
129 ok( ret, "Failed to convert name, error %#x\n", GetLastError() );
130 key_info.CertIssuer.cbData = size;
131 key_info.CertIssuer.pbData = encoded_name;
133 size = sizeof(public_key_info_buffer);
134 ret = CryptExportPublicKeyInfo( provider, AT_SIGNATURE, X509_ASN_ENCODING, public_key_info, &size );
135 ok( ret, "Failed to export public key, error %#x\n", GetLastError() );
136 cert_info.SubjectPublicKeyInfo = *public_key_info;
138 size = sizeof(hash_buffer);
139 ret = CryptHashPublicKeyInfo( provider, CALG_MD5, 0, X509_ASN_ENCODING, public_key_info, hash_buffer, &size );
140 ok( ret, "Failed to hash public key, error %#x\n", GetLastError() );
142 key_info.KeyId.cbData = size;
143 key_info.KeyId.pbData = hash_buffer;
145 RtlGenRandom( serial, sizeof(serial) );
146 key_info.CertSerialNumber.cbData = sizeof(serial);
147 key_info.CertSerialNumber.pbData = serial;
149 size = sizeof(encoded_key_id);
150 ret = CryptEncodeObject( X509_ASN_ENCODING, X509_AUTHORITY_KEY_ID, &key_info, encoded_key_id, &size );
151 ok( ret, "Failed to convert name, error %#x\n", GetLastError() );
153 extension.pszObjId = (char *)szOID_AUTHORITY_KEY_IDENTIFIER;
154 extension.fCritical = TRUE;
155 extension.Value.cbData = size;
156 extension.Value.pbData = encoded_key_id;
158 cert_info.dwVersion = CERT_V3;
159 cert_info.SerialNumber = key_info.CertSerialNumber;
160 cert_info.SignatureAlgorithm.pszObjId = (char *)szOID_RSA_SHA1RSA;
161 cert_info.Issuer = key_info.CertIssuer;
162 GetSystemTimeAsFileTime( &cert_info.NotBefore );
163 GetSystemTimeAsFileTime( &cert_info.NotAfter );
164 cert_info.NotAfter.dwHighDateTime += 1;
165 cert_info.Subject = key_info.CertIssuer;
166 cert_info.cExtension = 1;
167 cert_info.rgExtension = &extension;
168 algid.pszObjId = (char *)szOID_RSA_SHA1RSA;
169 size = sizeof(cert_buffer);
170 ret = CryptSignAndEncodeCertificate( provider, AT_SIGNATURE, X509_ASN_ENCODING, X509_CERT_TO_BE_SIGNED,
171 &cert_info, &algid, NULL, cert_buffer, &size );
172 ok( ret, "Failed to create certificate, error %#x\n", GetLastError() );
174 cert = CertCreateCertificateContext( X509_ASN_ENCODING, cert_buffer, size );
175 ok( !!cert, "Failed to create context, error %#x\n", GetLastError() );
177 size = sizeof(provider_nameA);
178 ret = CryptGetProvParam( provider, PP_NAME, provider_nameA, &size, 0 );
179 ok( ret, "Failed to get prov param, error %#x\n", GetLastError() );
180 MultiByteToWideChar( CP_ACP, 0, (char *)provider_nameA, -1, provider_nameW, ARRAY_SIZE(provider_nameW) );
182 provider_info.pwszContainerName = (WCHAR *)container_name;
183 provider_info.pwszProvName = provider_nameW;
184 provider_info.dwProvType = PROV_RSA_FULL;
185 provider_info.dwKeySpec = AT_SIGNATURE;
186 ret = CertSetCertificateContextProperty( cert, CERT_KEY_PROV_INFO_PROP_ID, 0, &provider_info );
187 ok( ret, "Failed to set provider info, error %#x\n", GetLastError() );
189 ret = CryptReleaseContext( provider, 0 );
190 ok( ret, "failed to release context, error %u\n", GetLastError() );
192 root_store = CertOpenStore( CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE, L"root" );
193 if (!root_store && GetLastError() == ERROR_ACCESS_DENIED)
195 win_skip( "Failed to open root store.\n" );
196 ret = CertFreeCertificateContext( cert );
197 ok( ret, "Failed to free certificate, error %u\n", GetLastError() );
198 return NULL;
200 ok( !!root_store, "Failed to open store, error %u\n", GetLastError() );
201 ret = CertAddCertificateContextToStore( root_store, cert, CERT_STORE_ADD_ALWAYS, NULL );
202 if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
204 win_skip( "Failed to add self-signed certificate to store.\n" );
205 ret = CertFreeCertificateContext( cert );
206 ok( ret, "Failed to free certificate, error %u\n", GetLastError() );
207 ret = CertCloseStore( root_store, CERT_CLOSE_STORE_CHECK_FLAG );
208 ok( ret, "Failed to close store, error %u\n", GetLastError() );
209 return NULL;
211 ok( ret, "Failed to add certificate, error %u\n", GetLastError() );
212 ret = CertCloseStore( root_store, CERT_CLOSE_STORE_CHECK_FLAG );
213 ok( ret, "Failed to close store, error %u\n", GetLastError() );
215 pub_store = CertOpenStore( CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0,
216 CERT_SYSTEM_STORE_LOCAL_MACHINE, L"trustedpublisher" );
217 ok( !!pub_store, "Failed to open store, error %u\n", GetLastError() );
218 ret = CertAddCertificateContextToStore( pub_store, cert, CERT_STORE_ADD_ALWAYS, NULL );
219 ok( ret, "Failed to add certificate, error %u\n", GetLastError() );
220 ret = CertCloseStore( pub_store, CERT_CLOSE_STORE_CHECK_FLAG );
221 ok( ret, "Failed to close store, error %u\n", GetLastError() );
223 subject.dwSubjectChoice = 1;
224 subject.pdwIndex = &index;
225 subject.pSignerFileInfo = &file;
226 file.pwszFileName = (WCHAR *)filename;
227 signer.dwCertChoice = 2;
228 signer.pCertStoreInfo = &store;
229 store.pSigningCert = cert;
230 store.dwCertPolicy = 0;
231 signature.algidHash = CALG_SHA_256;
232 signature.dwAttrChoice = SIGNER_AUTHCODE_ATTR;
233 signature.pAttrAuthcode = &authcode;
234 authcode.pwszName = L"";
235 authcode.pwszInfo = L"";
236 hr = pSignerSign( &subject, &signer, &signature, NULL, NULL, NULL, NULL );
237 todo_wine
238 ok( hr == S_OK || broken( hr == NTE_BAD_ALGID ) /* < 7 */, "Failed to sign, hr %#x\n", hr );
240 return cert;
243 static void testsign_cleanup( const CERT_CONTEXT *cert )
245 HCERTSTORE root_store, pub_store;
246 const CERT_CONTEXT *store_cert;
247 HCRYPTPROV provider;
248 BOOL ret;
250 root_store = CertOpenStore( CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE, L"root" );
251 ok( !!root_store, "Failed to open store, error %u\n", GetLastError() );
252 store_cert = CertFindCertificateInStore( root_store, X509_ASN_ENCODING, 0, CERT_FIND_EXISTING, cert, NULL );
253 ok( !!store_cert, "Failed to find root certificate, error %u\n", GetLastError() );
254 ret = CertDeleteCertificateFromStore( store_cert );
255 ok( ret, "Failed to remove certificate, error %u\n", GetLastError() );
256 ret = CertCloseStore( root_store, CERT_CLOSE_STORE_CHECK_FLAG );
257 ok( ret, "Failed to close store, error %u\n", GetLastError() );
259 pub_store = CertOpenStore( CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0,
260 CERT_SYSTEM_STORE_LOCAL_MACHINE, L"trustedpublisher" );
261 ok( !!pub_store, "Failed to open store, error %u\n", GetLastError() );
262 store_cert = CertFindCertificateInStore( pub_store, X509_ASN_ENCODING, 0, CERT_FIND_EXISTING, cert, NULL );
263 ok( !!store_cert, "Failed to find publisher certificate, error %u\n", GetLastError() );
264 ret = CertDeleteCertificateFromStore( store_cert );
265 ok( ret, "Failed to remove certificate, error %u\n", GetLastError() );
266 ret = CertCloseStore( pub_store, CERT_CLOSE_STORE_CHECK_FLAG );
267 ok( ret, "Failed to close store, error %u\n", GetLastError() );
269 ret = CertFreeCertificateContext( cert );
270 ok( ret, "Failed to free certificate, error %u\n", GetLastError() );
272 ret = CryptAcquireContextW( &provider, container_name, NULL, PROV_RSA_FULL, CRYPT_DELETEKEYSET );
273 ok( ret, "Failed to delete container, error %#x\n", GetLastError() );
276 static void load_resource( const WCHAR *name, WCHAR *filename )
278 static WCHAR path[MAX_PATH];
279 DWORD written;
280 HANDLE file;
281 HRSRC res;
282 void *ptr;
284 GetTempPathW( ARRAY_SIZE(path), path );
285 GetTempFileNameW( path, name, 0, filename );
287 file = CreateFileW( filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 );
288 ok( file != INVALID_HANDLE_VALUE, "failed to create %s, error %u\n", debugstr_w(filename), GetLastError() );
290 res = FindResourceW( NULL, name, L"TESTDLL" );
291 ok( res != 0, "couldn't find resource\n" );
292 ptr = LockResource( LoadResource( GetModuleHandleW( NULL ), res ) );
293 WriteFile( file, ptr, SizeofResource( GetModuleHandleW( NULL ), res ), &written, NULL );
294 ok( written == SizeofResource( GetModuleHandleW( NULL ), res ), "couldn't write resource\n" );
295 CloseHandle( file );
298 #ifdef __i386__
299 #define EXT "x86"
300 #elif defined(__x86_64__)
301 #define EXT "amd64"
302 #elif defined(__arm__)
303 #define EXT "arm"
304 #elif defined(__aarch64__)
305 #define EXT "arm64"
306 #else
307 #define EXT
308 #endif
310 static const char inf_text[] =
311 "[Version]\n"
312 "Signature=$Chicago$\n"
313 "ClassGuid={4d36e97d-e325-11ce-bfc1-08002be10318}\n"
314 "CatalogFile=winetest.cat\n"
315 "DriverVer=09/21/2006,6.0.5736.1\n"
317 "[Manufacturer]\n"
318 "Wine=mfg_section,NT" EXT "\n"
320 "[mfg_section.NT" EXT "]\n"
321 "Wine test root driver=device_section,test_hardware_id\n"
323 "[device_section.NT" EXT "]\n"
324 "CopyFiles=file_section\n"
326 "[device_section.NT" EXT ".Services]\n"
327 "AddService=winetest,0x2,svc_section\n"
329 "[file_section]\n"
330 "winetest.sys\n"
332 "[SourceDisksFiles]\n"
333 "winetest.sys=1\n"
335 "[SourceDisksNames]\n"
336 "1=,winetest.sys\n"
338 "[DestinationDirs]\n"
339 "DefaultDestDir=12\n"
341 "[svc_section]\n"
342 "ServiceBinary=%12%\\winetest.sys\n"
343 "ServiceType=1\n"
344 "StartType=3\n"
345 "ErrorControl=1\n"
346 "LoadOrderGroup=Extended Base\n"
347 "DisplayName=\"winetest bus driver\"\n"
348 "; they don't sleep anymore, on the beach\n";
350 static void add_file_to_catalog( HANDLE catalog, const WCHAR *file )
352 SIP_SUBJECTINFO subject_info = {sizeof(SIP_SUBJECTINFO)};
353 SIP_INDIRECT_DATA *indirect_data;
354 const WCHAR *filepart = file;
355 CRYPTCATMEMBER *member;
356 WCHAR hash_buffer[100];
357 GUID subject_guid;
358 unsigned int i;
359 DWORD size;
360 BOOL ret;
362 ret = CryptSIPRetrieveSubjectGuidForCatalogFile( file, NULL, &subject_guid );
363 todo_wine
364 ok( ret, "Failed to get subject guid, error %u\n", GetLastError() );
366 size = 0;
367 subject_info.pgSubjectType = &subject_guid;
368 subject_info.pwsFileName = file;
369 subject_info.DigestAlgorithm.pszObjId = (char *)szOID_OIWSEC_sha1;
370 subject_info.dwFlags = SPC_INC_PE_RESOURCES_FLAG | SPC_INC_PE_IMPORT_ADDR_TABLE_FLAG |
371 SPC_EXC_PE_PAGE_HASHES_FLAG | 0x10000;
372 ret = CryptSIPCreateIndirectData( &subject_info, &size, NULL );
373 todo_wine
374 ok( ret, "Failed to get indirect data size, error %u\n", GetLastError() );
376 indirect_data = malloc( size );
377 ret = CryptSIPCreateIndirectData( &subject_info, &size, indirect_data );
378 todo_wine
379 ok( ret, "Failed to get indirect data, error %u\n", GetLastError() );
380 if (ret)
382 memset( hash_buffer, 0, sizeof(hash_buffer) );
383 for (i = 0; i < indirect_data->Digest.cbData; ++i)
384 swprintf( &hash_buffer[i * 2], 2, L"%02X", indirect_data->Digest.pbData[i] );
386 member = CryptCATPutMemberInfo( catalog, (WCHAR *)file, hash_buffer, &subject_guid,
387 0, size, (BYTE *)indirect_data );
388 ok( !!member, "Failed to write member, error %u\n", GetLastError() );
390 if (wcsrchr( file, '\\' )) filepart = wcsrchr( file, '\\' ) + 1;
392 ret = !!CryptCATPutAttrInfo( catalog, member, (WCHAR *)L"File",
393 CRYPTCAT_ATTR_NAMEASCII | CRYPTCAT_ATTR_DATAASCII | CRYPTCAT_ATTR_AUTHENTICATED,
394 (wcslen( filepart ) + 1) * 2, (BYTE *)filepart );
395 ok( ret, "Failed to write attr, error %u\n", GetLastError() );
397 ret = !!CryptCATPutAttrInfo( catalog, member, (WCHAR *)L"OSAttr",
398 CRYPTCAT_ATTR_NAMEASCII | CRYPTCAT_ATTR_DATAASCII | CRYPTCAT_ATTR_AUTHENTICATED,
399 sizeof(L"2:6.0"), (BYTE *)L"2:6.0" );
400 ok( ret, "Failed to write attr, error %u\n", GetLastError() );
404 static void unload_driver( SC_HANDLE service )
406 SERVICE_STATUS status;
408 ControlService( service, SERVICE_CONTROL_STOP, &status );
409 while (status.dwCurrentState == SERVICE_STOP_PENDING)
411 BOOL ret;
412 Sleep( 100 );
413 ret = QueryServiceStatus( service, &status );
414 ok( ret, "QueryServiceStatus failed: %u\n", GetLastError() );
416 ok( status.dwCurrentState == SERVICE_STOPPED, "expected SERVICE_STOPPED, got %d\n", status.dwCurrentState );
418 DeleteService( service );
419 CloseServiceHandle( service );
422 static void pnp_driver_stop(void)
424 SP_DEVINFO_DATA device = {sizeof(SP_DEVINFO_DATA)};
425 WCHAR path[MAX_PATH], dest[MAX_PATH], *filepart;
426 SC_HANDLE manager, service;
427 char buffer[512];
428 HDEVINFO set;
429 HANDLE file;
430 DWORD size;
431 BOOL ret;
433 set = SetupDiCreateDeviceInfoList( NULL, NULL );
434 ok( set != INVALID_HANDLE_VALUE, "failed to create device list, error %u\n", GetLastError() );
436 ret = SetupDiOpenDeviceInfoW( set, L"root\\winetest\\0", NULL, 0, &device );
437 if (!ret && GetLastError() == ERROR_NO_SUCH_DEVINST)
439 ret = SetupDiDestroyDeviceInfoList( set );
440 ok( ret, "failed to destroy set, error %u\n", GetLastError() );
441 return;
443 ok( ret, "failed to open device, error %u\n", GetLastError() );
445 ret = SetupDiCallClassInstaller( DIF_REMOVE, set, &device );
446 ok( ret, "failed to remove device, error %u\n", GetLastError() );
448 file = CreateFileW( L"\\\\?\\root#winetest#0#{deadbeef-29ef-4538-a5fd-b69573a362c0}", 0, 0,
449 NULL, OPEN_EXISTING, 0, NULL );
450 ok( file == INVALID_HANDLE_VALUE, "expected failure\n" );
451 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "got error %u\n", GetLastError() );
453 ret = SetupDiDestroyDeviceInfoList( set );
454 ok( ret, "failed to destroy set, error %u\n", GetLastError() );
456 /* Windows stops the service but does not delete it. */
457 manager = OpenSCManagerW( NULL, NULL, SC_MANAGER_CONNECT );
458 ok( !!manager, "failed to open service manager, error %u\n", GetLastError() );
460 service = OpenServiceW( manager, L"winetest", SERVICE_STOP | DELETE );
461 if (service) unload_driver( service );
462 else ok( GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST, "got error %u\n", GetLastError() );
464 CloseServiceHandle( manager );
466 SetFilePointer( okfile, 0, NULL, FILE_BEGIN );
469 ReadFile( okfile, buffer, sizeof(buffer), &size, NULL );
470 printf( "%.*s", size, buffer );
471 } while (size == sizeof(buffer));
472 SetFilePointer( okfile, 0, NULL, FILE_BEGIN );
473 SetEndOfFile( okfile );
475 winetest_add_failures( InterlockedExchange( &test_data->failures, 0 ) );
476 winetest_add_failures( InterlockedExchange( &test_data->todo_failures, 0 ) );
478 GetFullPathNameW( L"winetest.inf", ARRAY_SIZE(path), path, NULL );
479 ret = SetupCopyOEMInfW( path, NULL, 0, 0, dest, ARRAY_SIZE(dest), NULL, &filepart );
480 ok( ret, "Failed to copy INF, error %u\n", GetLastError() );
481 ret = SetupUninstallOEMInfW( filepart, 0, NULL );
482 ok( ret, "Failed to uninstall INF, error %u\n", GetLastError() );
484 ret = DeleteFileW( L"winetest.cat" );
485 ok( ret, "Failed to delete file, error %u\n", GetLastError() );
486 ret = DeleteFileW( L"winetest.inf" );
487 ok( ret, "Failed to delete file, error %u\n", GetLastError() );
488 ret = DeleteFileW( L"winetest.sys" );
489 ok( ret, "Failed to delete file, error %u\n", GetLastError() );
490 /* Windows 10 apparently deletes the image in SetupUninstallOEMInf(). */
491 ret = DeleteFileW( L"C:/windows/system32/drivers/winetest.sys" );
492 ok( ret || GetLastError() == ERROR_FILE_NOT_FOUND, "Failed to delete file, error %u\n", GetLastError() );
495 static BOOL pnp_driver_start( const WCHAR *resource )
497 static const WCHAR hardware_id[] = L"test_hardware_id\0";
498 SP_DEVINFO_DATA device = {sizeof(SP_DEVINFO_DATA)};
499 WCHAR path[MAX_PATH], filename[MAX_PATH];
500 SC_HANDLE manager, service;
501 const CERT_CONTEXT *cert;
502 int old_mute_threshold;
503 BOOL ret, need_reboot;
504 HANDLE catalog;
505 HDEVINFO set;
506 FILE *f;
508 old_mute_threshold = winetest_mute_threshold;
509 winetest_mute_threshold = 1;
511 load_resource( resource, filename );
512 ret = MoveFileExW( filename, L"winetest.sys", MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING );
513 ok( ret, "failed to move file, error %u\n", GetLastError() );
515 f = fopen( "winetest.inf", "w" );
516 ok( !!f, "failed to open winetest.inf: %s\n", strerror( errno ) );
517 fputs( inf_text, f );
518 fclose( f );
520 /* Create the catalog file. */
522 catalog = CryptCATOpen( (WCHAR *)L"winetest.cat", CRYPTCAT_OPEN_CREATENEW, 0, CRYPTCAT_VERSION_1, 0 );
523 ok( catalog != INVALID_HANDLE_VALUE, "Failed to create catalog, error %u\n", GetLastError() );
525 add_file_to_catalog( catalog, L"winetest.sys" );
526 add_file_to_catalog( catalog, L"winetest.inf" );
528 ret = CryptCATPersistStore( catalog );
529 todo_wine
530 ok( ret, "Failed to write catalog, error %u\n", GetLastError() );
532 ret = CryptCATClose( catalog );
533 ok( ret, "Failed to close catalog, error %u\n", GetLastError() );
535 if (!(cert = testsign_sign( L"winetest.cat" )))
537 ret = DeleteFileW( L"winetest.cat" );
538 ok( ret, "Failed to delete file, error %u\n", GetLastError() );
539 ret = DeleteFileW( L"winetest.inf" );
540 ok( ret, "Failed to delete file, error %u\n", GetLastError() );
541 ret = DeleteFileW( L"winetest.sys" );
542 ok( ret, "Failed to delete file, error %u\n", GetLastError() );
543 winetest_mute_threshold = old_mute_threshold;
544 return FALSE;
547 /* Install the driver. */
549 set = SetupDiCreateDeviceInfoList( NULL, NULL );
550 ok( set != INVALID_HANDLE_VALUE, "failed to create device list, error %u\n", GetLastError() );
552 ret = SetupDiCreateDeviceInfoW( set, L"root\\winetest\\0", &GUID_NULL, NULL, NULL, 0, &device );
553 ok( ret, "failed to create device, error %#x\n", GetLastError() );
555 ret = SetupDiSetDeviceRegistryPropertyW( set, &device, SPDRP_HARDWAREID, (const BYTE *)hardware_id,
556 sizeof(hardware_id) );
557 ok( ret, "failed to create set hardware ID, error %u\n", GetLastError() );
559 ret = SetupDiCallClassInstaller( DIF_REGISTERDEVICE, set, &device );
560 ok( ret, "failed to register device, error %u\n", GetLastError() );
562 ret = SetupDiDestroyDeviceInfoList( set );
563 ok( ret, "failed to destroy set, error %u\n", GetLastError() );
565 GetFullPathNameW( L"winetest.inf", ARRAY_SIZE(path), path, NULL );
567 ret = UpdateDriverForPlugAndPlayDevicesW( NULL, hardware_id, path, INSTALLFLAG_FORCE, &need_reboot );
568 ok( ret, "failed to install device, error %u\n", GetLastError() );
569 ok( !need_reboot, "expected no reboot necessary\n" );
571 testsign_cleanup( cert );
573 /* Check that the service is created and started. */
574 manager = OpenSCManagerW( NULL, NULL, SC_MANAGER_CONNECT );
575 ok( !!manager, "failed to open service manager, error %u\n", GetLastError() );
577 service = OpenServiceW( manager, L"winetest", SERVICE_START );
578 ok( !!service, "failed to open service, error %u\n", GetLastError() );
580 ret = StartServiceW( service, 0, NULL );
581 ok( !ret, "service didn't start automatically\n" );
582 if (!ret && GetLastError() != ERROR_SERVICE_ALREADY_RUNNING)
584 /* If Secure Boot is enabled or the machine is 64-bit, it will reject an unsigned driver. */
585 ok( GetLastError() == ERROR_DRIVER_BLOCKED || GetLastError() == ERROR_INVALID_IMAGE_HASH,
586 "unexpected error %u\n", GetLastError() );
587 win_skip( "Failed to start service; probably your machine doesn't accept unsigned drivers.\n" );
590 CloseServiceHandle( service );
591 CloseServiceHandle( manager );
593 winetest_mute_threshold = old_mute_threshold;
594 return ret || GetLastError() == ERROR_SERVICE_ALREADY_RUNNING;
597 #define check_member_( file, line, val, exp, fmt, member ) \
598 ok_(file, line)( (val).member == (exp).member, "got " #member " " fmt "\n", (val).member )
599 #define check_member( val, exp, fmt, member ) \
600 check_member_( __FILE__, __LINE__, val, exp, fmt, member )
602 #define check_member_guid_( file, line, val, exp, member ) \
603 ok_(file, line)( IsEqualGUID( &(val).member, &(exp).member ), "got " #member " %s\n", debugstr_guid(&(val).member) )
604 #define check_member_guid( val, exp, member ) \
605 check_member_guid_( __FILE__, __LINE__, val, exp, member )
607 #define check_member_wstr_( file, line, val, exp, member ) \
608 ok_(file, line)( !wcscmp( (val).member, (exp).member ), "got " #member " %s\n", debugstr_w((val).member) )
609 #define check_member_wstr( val, exp, member ) \
610 check_member_wstr_( __FILE__, __LINE__, val, exp, member )
612 #define check_hidp_caps( a, b ) check_hidp_caps_( __LINE__, a, b )
613 static inline void check_hidp_caps_( int line, HIDP_CAPS *caps, const HIDP_CAPS *exp )
615 check_member_( __FILE__, line, *caps, *exp, "%04x", Usage );
616 check_member_( __FILE__, line, *caps, *exp, "%04x", UsagePage );
617 check_member_( __FILE__, line, *caps, *exp, "%d", InputReportByteLength );
618 check_member_( __FILE__, line, *caps, *exp, "%d", OutputReportByteLength );
619 check_member_( __FILE__, line, *caps, *exp, "%d", FeatureReportByteLength );
620 check_member_( __FILE__, line, *caps, *exp, "%d", NumberLinkCollectionNodes );
621 check_member_( __FILE__, line, *caps, *exp, "%d", NumberInputButtonCaps );
622 check_member_( __FILE__, line, *caps, *exp, "%d", NumberInputValueCaps );
623 check_member_( __FILE__, line, *caps, *exp, "%d", NumberInputDataIndices );
624 check_member_( __FILE__, line, *caps, *exp, "%d", NumberOutputButtonCaps );
625 check_member_( __FILE__, line, *caps, *exp, "%d", NumberOutputValueCaps );
626 check_member_( __FILE__, line, *caps, *exp, "%d", NumberOutputDataIndices );
627 check_member_( __FILE__, line, *caps, *exp, "%d", NumberFeatureButtonCaps );
628 check_member_( __FILE__, line, *caps, *exp, "%d", NumberFeatureValueCaps );
629 check_member_( __FILE__, line, *caps, *exp, "%d", NumberFeatureDataIndices );
632 #define check_hidp_link_collection_node( a, b ) check_hidp_link_collection_node_( __LINE__, a, b )
633 static inline void check_hidp_link_collection_node_( int line, HIDP_LINK_COLLECTION_NODE *node,
634 const HIDP_LINK_COLLECTION_NODE *exp )
636 check_member_( __FILE__, line, *node, *exp, "%04x", LinkUsage );
637 check_member_( __FILE__, line, *node, *exp, "%04x", LinkUsagePage );
638 check_member_( __FILE__, line, *node, *exp, "%d", Parent );
639 check_member_( __FILE__, line, *node, *exp, "%d", NumberOfChildren );
640 check_member_( __FILE__, line, *node, *exp, "%d", NextSibling );
641 check_member_( __FILE__, line, *node, *exp, "%d", FirstChild );
642 check_member_( __FILE__, line, *node, *exp, "%d", CollectionType );
643 check_member_( __FILE__, line, *node, *exp, "%d", IsAlias );
646 #define check_hidp_button_caps( a, b ) check_hidp_button_caps_( __LINE__, a, b )
647 static inline void check_hidp_button_caps_( int line, HIDP_BUTTON_CAPS *caps, const HIDP_BUTTON_CAPS *exp )
649 check_member_( __FILE__, line, *caps, *exp, "%04x", UsagePage );
650 check_member_( __FILE__, line, *caps, *exp, "%d", ReportID );
651 check_member_( __FILE__, line, *caps, *exp, "%d", IsAlias );
652 check_member_( __FILE__, line, *caps, *exp, "%d", BitField );
653 check_member_( __FILE__, line, *caps, *exp, "%d", LinkCollection );
654 check_member_( __FILE__, line, *caps, *exp, "%04x", LinkUsage );
655 check_member_( __FILE__, line, *caps, *exp, "%04x", LinkUsagePage );
656 check_member_( __FILE__, line, *caps, *exp, "%d", IsRange );
657 check_member_( __FILE__, line, *caps, *exp, "%d", IsStringRange );
658 check_member_( __FILE__, line, *caps, *exp, "%d", IsDesignatorRange );
659 check_member_( __FILE__, line, *caps, *exp, "%d", IsAbsolute );
661 if (!caps->IsRange && !exp->IsRange)
663 check_member_( __FILE__, line, *caps, *exp, "%04x", NotRange.Usage );
664 check_member_( __FILE__, line, *caps, *exp, "%d", NotRange.DataIndex );
666 else if (caps->IsRange && exp->IsRange)
668 check_member_( __FILE__, line, *caps, *exp, "%04x", Range.UsageMin );
669 check_member_( __FILE__, line, *caps, *exp, "%04x", Range.UsageMax );
670 check_member_( __FILE__, line, *caps, *exp, "%d", Range.DataIndexMin );
671 check_member_( __FILE__, line, *caps, *exp, "%d", Range.DataIndexMax );
674 if (!caps->IsRange && !exp->IsRange)
675 check_member_( __FILE__, line, *caps, *exp, "%d", NotRange.StringIndex );
676 else if (caps->IsStringRange && exp->IsStringRange)
678 check_member_( __FILE__, line, *caps, *exp, "%d", Range.StringMin );
679 check_member_( __FILE__, line, *caps, *exp, "%d", Range.StringMax );
682 if (!caps->IsDesignatorRange && !exp->IsDesignatorRange)
683 check_member_( __FILE__, line, *caps, *exp, "%d", NotRange.DesignatorIndex );
684 else if (caps->IsDesignatorRange && exp->IsDesignatorRange)
686 check_member_( __FILE__, line, *caps, *exp, "%d", Range.DesignatorMin );
687 check_member_( __FILE__, line, *caps, *exp, "%d", Range.DesignatorMax );
691 #define check_hidp_value_caps( a, b ) check_hidp_value_caps_( __LINE__, a, b )
692 static inline void check_hidp_value_caps_( int line, HIDP_VALUE_CAPS *caps, const HIDP_VALUE_CAPS *exp )
694 check_member_( __FILE__, line, *caps, *exp, "%04x", UsagePage );
695 check_member_( __FILE__, line, *caps, *exp, "%d", ReportID );
696 check_member_( __FILE__, line, *caps, *exp, "%d", IsAlias );
697 check_member_( __FILE__, line, *caps, *exp, "%d", BitField );
698 check_member_( __FILE__, line, *caps, *exp, "%d", LinkCollection );
699 check_member_( __FILE__, line, *caps, *exp, "%d", LinkUsage );
700 check_member_( __FILE__, line, *caps, *exp, "%d", LinkUsagePage );
701 check_member_( __FILE__, line, *caps, *exp, "%d", IsRange );
702 check_member_( __FILE__, line, *caps, *exp, "%d", IsStringRange );
703 check_member_( __FILE__, line, *caps, *exp, "%d", IsDesignatorRange );
704 check_member_( __FILE__, line, *caps, *exp, "%d", IsAbsolute );
706 check_member_( __FILE__, line, *caps, *exp, "%d", HasNull );
707 check_member_( __FILE__, line, *caps, *exp, "%d", BitSize );
708 check_member_( __FILE__, line, *caps, *exp, "%d", ReportCount );
709 check_member_( __FILE__, line, *caps, *exp, "%d", UnitsExp );
710 check_member_( __FILE__, line, *caps, *exp, "%d", Units );
711 check_member_( __FILE__, line, *caps, *exp, "%d", LogicalMin );
712 check_member_( __FILE__, line, *caps, *exp, "%d", LogicalMax );
713 check_member_( __FILE__, line, *caps, *exp, "%d", PhysicalMin );
714 check_member_( __FILE__, line, *caps, *exp, "%d", PhysicalMax );
716 if (!caps->IsRange && !exp->IsRange)
718 check_member_( __FILE__, line, *caps, *exp, "%04x", NotRange.Usage );
719 check_member_( __FILE__, line, *caps, *exp, "%d", NotRange.DataIndex );
721 else if (caps->IsRange && exp->IsRange)
723 check_member_( __FILE__, line, *caps, *exp, "%04x", Range.UsageMin );
724 check_member_( __FILE__, line, *caps, *exp, "%04x", Range.UsageMax );
725 check_member_( __FILE__, line, *caps, *exp, "%d", Range.DataIndexMin );
726 check_member_( __FILE__, line, *caps, *exp, "%d", Range.DataIndexMax );
729 if (!caps->IsRange && !exp->IsRange)
730 check_member_( __FILE__, line, *caps, *exp, "%d", NotRange.StringIndex );
731 else if (caps->IsStringRange && exp->IsStringRange)
733 check_member_( __FILE__, line, *caps, *exp, "%d", Range.StringMin );
734 check_member_( __FILE__, line, *caps, *exp, "%d", Range.StringMax );
737 if (!caps->IsDesignatorRange && !exp->IsDesignatorRange)
738 check_member_( __FILE__, line, *caps, *exp, "%d", NotRange.DesignatorIndex );
739 else if (caps->IsDesignatorRange && exp->IsDesignatorRange)
741 check_member_( __FILE__, line, *caps, *exp, "%d", Range.DesignatorMin );
742 check_member_( __FILE__, line, *caps, *exp, "%d", Range.DesignatorMax );
746 #define sync_ioctl( a, b, c, d, e, f, g ) sync_ioctl_( __LINE__, a, b, c, d, e, f, g )
747 static BOOL sync_ioctl_( int line, HANDLE file, DWORD code, void *in_buf, DWORD in_len, void *out_buf, DWORD *ret_len, DWORD timeout )
749 DWORD res, out_len = ret_len ? *ret_len : 0;
750 OVERLAPPED ovl = {0};
751 BOOL ret;
753 ovl.hEvent = CreateEventW( NULL, TRUE, FALSE, NULL );
754 ret = DeviceIoControl( file, code, in_buf, in_len, out_buf, out_len, &out_len, &ovl );
755 if (!ret && GetLastError() == ERROR_IO_PENDING)
757 res = WaitForSingleObject( ovl.hEvent, timeout );
758 ok_(__FILE__, line)( res == WAIT_OBJECT_0, "WaitForSingleObject returned %#x\n", res );
759 ret = GetOverlappedResult( file, &ovl, &out_len, FALSE );
760 ok_(__FILE__, line)( ret, "GetOverlappedResult returned %u\n", GetLastError() );
762 CloseHandle( ovl.hEvent );
764 if (ret_len) *ret_len = out_len;
765 return ret;
768 #define set_hid_expect( a, b, c ) set_hid_expect_( __LINE__, a, b, c )
769 static void set_hid_expect_( int line, HANDLE file, struct hid_expect *expect, DWORD expect_size )
771 const char *source_file;
772 BOOL ret;
773 int i;
775 source_file = strrchr( __FILE__, '/' );
776 if (!source_file) source_file = strrchr( __FILE__, '\\' );
777 if (!source_file) source_file = __FILE__;
778 else source_file++;
780 for (i = 0; i < expect_size / sizeof(struct hid_expect); ++i)
781 snprintf( expect[i].context, ARRAY_SIZE(expect[i].context), "%s:%d", source_file, line );
783 ret = sync_ioctl_( line, file, IOCTL_WINETEST_HID_SET_EXPECT, expect, expect_size, NULL, 0, INFINITE );
784 ok_(__FILE__, line)( ret, "IOCTL_WINETEST_HID_SET_EXPECT failed, last error %u\n", GetLastError() );
787 #define wait_hid_expect( a, b ) wait_hid_expect_( __LINE__, a, b )
788 static void wait_hid_expect_( int line, HANDLE file, DWORD timeout )
790 BOOL ret = sync_ioctl_( line, file, IOCTL_WINETEST_HID_WAIT_EXPECT, NULL, 0, NULL, 0, timeout );
791 ok_(__FILE__, line)( ret, "IOCTL_WINETEST_HID_WAIT_EXPECT failed, last error %u\n", GetLastError() );
793 set_hid_expect_( line, file, NULL, 0 );
796 #define send_hid_input( a, b, c ) send_hid_input_( __LINE__, a, b, c )
797 static void send_hid_input_( int line, HANDLE file, struct hid_expect *expect, DWORD expect_size )
799 const char *source_file;
800 BOOL ret;
801 int i;
803 source_file = strrchr( __FILE__, '/' );
804 if (!source_file) source_file = strrchr( __FILE__, '\\' );
805 if (!source_file) source_file = __FILE__;
806 else source_file++;
808 for (i = 0; i < expect_size / sizeof(struct hid_expect); ++i)
809 snprintf( expect[i].context, ARRAY_SIZE(expect[i].context), "%s:%d", source_file, line );
811 ret = sync_ioctl( file, IOCTL_WINETEST_HID_SEND_INPUT, expect, expect_size, NULL, 0, INFINITE );
812 ok( ret, "IOCTL_WINETEST_HID_SEND_INPUT failed, last error %u\n", GetLastError() );
815 static void test_hidp_get_input( HANDLE file, int report_id, ULONG report_len, PHIDP_PREPARSED_DATA preparsed )
817 struct hid_expect expect[] =
820 .code = IOCTL_HID_GET_INPUT_REPORT,
821 .report_id = report_id,
822 .report_len = report_len - (report_id ? 0 : 1),
823 .report_buf = {report_id ? report_id : 0xa5,0xa5,2},
824 .ret_length = 3,
825 .ret_status = STATUS_SUCCESS,
828 .code = IOCTL_HID_GET_INPUT_REPORT,
829 .report_id = report_id,
830 .report_len = 2 * report_len - (report_id ? 0 : 1),
831 .report_buf = {report_id ? report_id : 0xa5,0xa5,1},
832 .ret_length = 3,
833 .ret_status = STATUS_SUCCESS,
837 char buffer[200], report[200];
838 NTSTATUS status;
839 ULONG length;
840 BOOL ret;
842 memset( report, 0xcd, sizeof(report) );
843 status = HidP_InitializeReportForID( HidP_Input, report_id, preparsed, report, report_len );
844 ok( status == HIDP_STATUS_SUCCESS, "HidP_InitializeReportForID returned %#x\n", status );
846 SetLastError( 0xdeadbeef );
847 ret = HidD_GetInputReport( file, report, 0 );
848 ok( !ret, "HidD_GetInputReport succeeded\n" );
849 ok( GetLastError() == ERROR_INVALID_USER_BUFFER, "HidD_GetInputReport returned error %u\n", GetLastError() );
851 SetLastError( 0xdeadbeef );
852 ret = HidD_GetInputReport( file, report, report_len - 1 );
853 ok( !ret, "HidD_GetInputReport succeeded\n" );
854 ok( GetLastError() == ERROR_INVALID_PARAMETER || broken( GetLastError() == ERROR_CRC ),
855 "HidD_GetInputReport returned error %u\n", GetLastError() );
857 if (!report_id)
859 struct hid_expect broken_expect =
861 .code = IOCTL_HID_GET_INPUT_REPORT,
862 .broken = TRUE,
863 .report_len = report_len - 1,
864 .report_buf =
866 0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
867 0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
868 0x5a,0x5a,0x5a,0x5a,0x5a,
870 .ret_length = 3,
871 .ret_status = STATUS_SUCCESS,
874 set_hid_expect( file, &broken_expect, sizeof(broken_expect) );
877 SetLastError( 0xdeadbeef );
878 memset( buffer, 0x5a, sizeof(buffer) );
879 ret = HidD_GetInputReport( file, buffer, report_len );
880 if (report_id || broken( !ret ) /* w7u */)
882 ok( !ret, "HidD_GetInputReport succeeded, last error %u\n", GetLastError() );
883 ok( GetLastError() == ERROR_INVALID_PARAMETER || broken( GetLastError() == ERROR_CRC ),
884 "HidD_GetInputReport returned error %u\n", GetLastError() );
886 else
888 ok( ret, "HidD_GetInputReport failed, last error %u\n", GetLastError() );
889 ok( buffer[0] == 0x5a, "got buffer[0] %x, expected 0x5a\n", (BYTE)buffer[0] );
892 set_hid_expect( file, expect, sizeof(expect) );
894 SetLastError( 0xdeadbeef );
895 ret = HidD_GetInputReport( file, report, report_len );
896 ok( ret, "HidD_GetInputReport failed, last error %u\n", GetLastError() );
897 ok( report[0] == report_id, "got report[0] %02x, expected %02x\n", report[0], report_id );
899 SetLastError( 0xdeadbeef );
900 length = report_len * 2;
901 ret = sync_ioctl( file, IOCTL_HID_GET_INPUT_REPORT, NULL, 0, report, &length, INFINITE );
902 ok( ret, "IOCTL_HID_GET_INPUT_REPORT failed, last error %u\n", GetLastError() );
903 ok( length == 3, "got length %u, expected 3\n", length );
904 ok( report[0] == report_id, "got report[0] %02x, expected %02x\n", report[0], report_id );
906 set_hid_expect( file, NULL, 0 );
909 static void test_hidp_get_feature( HANDLE file, int report_id, ULONG report_len, PHIDP_PREPARSED_DATA preparsed )
911 struct hid_expect expect[] =
914 .code = IOCTL_HID_GET_FEATURE,
915 .report_id = report_id,
916 .report_len = report_len - (report_id ? 0 : 1),
917 .report_buf = {report_id ? report_id : 0xa5,0xa5,0xa5},
918 .ret_length = 3,
919 .ret_status = STATUS_SUCCESS,
922 .code = IOCTL_HID_GET_FEATURE,
923 .report_id = report_id,
924 .report_len = 2 * report_len - (report_id ? 0 : 1),
925 .report_buf = {report_id ? report_id : 0xa5,0xa5,0xa5},
926 .ret_length = 3,
927 .ret_status = STATUS_SUCCESS,
931 char buffer[200], report[200];
932 NTSTATUS status;
933 ULONG length;
934 BOOL ret;
936 memset( report, 0xcd, sizeof(report) );
937 status = HidP_InitializeReportForID( HidP_Feature, report_id, preparsed, report, report_len );
938 ok( status == HIDP_STATUS_SUCCESS, "HidP_InitializeReportForID returned %#x\n", status );
940 SetLastError( 0xdeadbeef );
941 ret = HidD_GetFeature( file, report, 0 );
942 ok( !ret, "HidD_GetFeature succeeded\n" );
943 ok( GetLastError() == ERROR_INVALID_USER_BUFFER, "HidD_GetFeature returned error %u\n", GetLastError() );
945 SetLastError( 0xdeadbeef );
946 ret = HidD_GetFeature( file, report, report_len - 1 );
947 ok( !ret, "HidD_GetFeature succeeded\n" );
948 ok( GetLastError() == ERROR_INVALID_PARAMETER || broken( GetLastError() == ERROR_CRC ),
949 "HidD_GetFeature returned error %u\n", GetLastError() );
951 if (!report_id)
953 struct hid_expect broken_expect =
955 .code = IOCTL_HID_GET_FEATURE,
956 .broken = TRUE,
957 .report_len = report_len - 1,
958 .report_buf =
960 0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
961 0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
962 0x5a,0x5a,0x5a,0x5a,0x5a,
964 .ret_length = 3,
965 .ret_status = STATUS_SUCCESS,
968 set_hid_expect( file, &broken_expect, sizeof(broken_expect) );
971 SetLastError( 0xdeadbeef );
972 memset( buffer, 0x5a, sizeof(buffer) );
973 ret = HidD_GetFeature( file, buffer, report_len );
974 if (report_id || broken( !ret ))
976 ok( !ret, "HidD_GetFeature succeeded, last error %u\n", GetLastError() );
977 ok( GetLastError() == ERROR_INVALID_PARAMETER || broken( GetLastError() == ERROR_CRC ),
978 "HidD_GetFeature returned error %u\n", GetLastError() );
980 else
982 ok( ret, "HidD_GetFeature failed, last error %u\n", GetLastError() );
983 ok( buffer[0] == 0x5a, "got buffer[0] %x, expected 0x5a\n", (BYTE)buffer[0] );
986 set_hid_expect( file, expect, sizeof(expect) );
988 SetLastError( 0xdeadbeef );
989 ret = HidD_GetFeature( file, report, report_len );
990 ok( ret, "HidD_GetFeature failed, last error %u\n", GetLastError() );
991 ok( report[0] == report_id, "got report[0] %02x, expected %02x\n", report[0], report_id );
993 length = report_len * 2;
994 SetLastError( 0xdeadbeef );
995 ret = sync_ioctl( file, IOCTL_HID_GET_FEATURE, NULL, 0, report, &length, INFINITE );
996 ok( ret, "IOCTL_HID_GET_FEATURE failed, last error %u\n", GetLastError() );
997 ok( length == 3, "got length %u, expected 3\n", length );
998 ok( report[0] == report_id, "got report[0] %02x, expected %02x\n", report[0], report_id );
1000 set_hid_expect( file, NULL, 0 );
1003 static void test_hidp_set_feature( HANDLE file, int report_id, ULONG report_len, PHIDP_PREPARSED_DATA preparsed )
1005 struct hid_expect expect[] =
1008 .code = IOCTL_HID_SET_FEATURE,
1009 .report_id = report_id,
1010 .report_len = report_len - (report_id ? 0 : 1),
1011 .report_buf = {report_id},
1012 .ret_length = 3,
1013 .ret_status = STATUS_SUCCESS,
1016 .code = IOCTL_HID_SET_FEATURE,
1017 .report_id = report_id,
1018 .report_len = report_len - (report_id ? 0 : 1),
1019 .report_buf =
1021 report_id,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1022 0,0,0,0,0,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,
1023 0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,
1025 .ret_length = 3,
1026 .ret_status = STATUS_SUCCESS,
1029 char buffer[200], report[200];
1030 NTSTATUS status;
1031 ULONG length;
1032 BOOL ret;
1034 memset( report, 0xcd, sizeof(report) );
1035 status = HidP_InitializeReportForID( HidP_Feature, report_id, preparsed, report, report_len );
1036 ok( status == HIDP_STATUS_SUCCESS, "HidP_InitializeReportForID returned %#x\n", status );
1038 SetLastError( 0xdeadbeef );
1039 ret = HidD_SetFeature( file, report, 0 );
1040 ok( !ret, "HidD_SetFeature succeeded\n" );
1041 ok( GetLastError() == ERROR_INVALID_USER_BUFFER, "HidD_SetFeature returned error %u\n", GetLastError() );
1043 SetLastError( 0xdeadbeef );
1044 ret = HidD_SetFeature( file, report, report_len - 1 );
1045 ok( !ret, "HidD_SetFeature succeeded\n" );
1046 ok( GetLastError() == ERROR_INVALID_PARAMETER || broken( GetLastError() == ERROR_CRC ),
1047 "HidD_SetFeature returned error %u\n", GetLastError() );
1049 if (!report_id)
1051 struct hid_expect broken_expect =
1053 .code = IOCTL_HID_SET_FEATURE,
1054 .broken = TRUE,
1055 .report_len = report_len - 1,
1056 .report_buf =
1058 0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
1059 0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
1060 0x5a,0x5a,0x5a,0x5a,0x5a,
1062 .ret_length = 3,
1063 .ret_status = STATUS_SUCCESS,
1066 set_hid_expect( file, &broken_expect, sizeof(broken_expect) );
1069 SetLastError( 0xdeadbeef );
1070 memset( buffer, 0x5a, sizeof(buffer) );
1071 ret = HidD_SetFeature( file, buffer, report_len );
1072 if (report_id || broken( !ret ))
1074 ok( !ret, "HidD_SetFeature succeeded, last error %u\n", GetLastError() );
1075 ok( GetLastError() == ERROR_INVALID_PARAMETER || broken( GetLastError() == ERROR_CRC ),
1076 "HidD_SetFeature returned error %u\n", GetLastError() );
1078 else
1080 ok( ret, "HidD_SetFeature failed, last error %u\n", GetLastError() );
1083 set_hid_expect( file, expect, sizeof(expect) );
1085 SetLastError( 0xdeadbeef );
1086 ret = HidD_SetFeature( file, report, report_len );
1087 ok( ret, "HidD_SetFeature failed, last error %u\n", GetLastError() );
1089 length = report_len * 2;
1090 SetLastError( 0xdeadbeef );
1091 ret = sync_ioctl( file, IOCTL_HID_SET_FEATURE, NULL, 0, report, &length, INFINITE );
1092 ok( !ret, "IOCTL_HID_SET_FEATURE succeeded\n" );
1093 ok( GetLastError() == ERROR_INVALID_USER_BUFFER, "IOCTL_HID_SET_FEATURE returned error %u\n",
1094 GetLastError() );
1095 length = 0;
1096 SetLastError( 0xdeadbeef );
1097 ret = sync_ioctl( file, IOCTL_HID_SET_FEATURE, report, report_len * 2, NULL, &length, INFINITE );
1098 ok( ret, "IOCTL_HID_SET_FEATURE failed, last error %u\n", GetLastError() );
1099 ok( length == 3, "got length %u, expected 3\n", length );
1101 set_hid_expect( file, NULL, 0 );
1104 static void test_hidp_set_output( HANDLE file, int report_id, ULONG report_len, PHIDP_PREPARSED_DATA preparsed )
1106 struct hid_expect expect[] =
1109 .code = IOCTL_HID_SET_OUTPUT_REPORT,
1110 .report_id = report_id,
1111 .report_len = report_len - (report_id ? 0 : 1),
1112 .report_buf = {report_id},
1113 .ret_length = 3,
1114 .ret_status = STATUS_SUCCESS,
1117 .code = IOCTL_HID_SET_OUTPUT_REPORT,
1118 .report_id = report_id,
1119 .report_len = report_len - (report_id ? 0 : 1),
1120 .report_buf = {report_id,0,0xcd,0xcd,0xcd},
1121 .ret_length = 3,
1122 .ret_status = STATUS_SUCCESS,
1126 char buffer[200], report[200];
1127 NTSTATUS status;
1128 ULONG length;
1129 BOOL ret;
1131 memset( report, 0xcd, sizeof(report) );
1132 status = HidP_InitializeReportForID( HidP_Output, report_id, preparsed, report, report_len );
1133 ok( status == HIDP_STATUS_REPORT_DOES_NOT_EXIST, "HidP_InitializeReportForID returned %#x\n", status );
1134 memset( report, 0, report_len );
1135 report[0] = report_id;
1137 SetLastError( 0xdeadbeef );
1138 ret = HidD_SetOutputReport( file, report, 0 );
1139 ok( !ret, "HidD_SetOutputReport succeeded\n" );
1140 ok( GetLastError() == ERROR_INVALID_USER_BUFFER, "HidD_SetOutputReport returned error %u\n",
1141 GetLastError() );
1143 SetLastError( 0xdeadbeef );
1144 ret = HidD_SetOutputReport( file, report, report_len - 1 );
1145 ok( !ret, "HidD_SetOutputReport succeeded\n" );
1146 ok( GetLastError() == ERROR_INVALID_PARAMETER || broken( GetLastError() == ERROR_CRC ),
1147 "HidD_SetOutputReport returned error %u\n", GetLastError() );
1149 if (!report_id)
1151 struct hid_expect broken_expect =
1153 .code = IOCTL_HID_SET_OUTPUT_REPORT,
1154 .broken = TRUE,
1155 .report_len = report_len - 1,
1156 .report_buf = {0x5a,0x5a},
1157 .ret_length = 3,
1158 .ret_status = STATUS_SUCCESS,
1161 set_hid_expect( file, &broken_expect, sizeof(broken_expect) );
1164 SetLastError( 0xdeadbeef );
1165 memset( buffer, 0x5a, sizeof(buffer) );
1166 ret = HidD_SetOutputReport( file, buffer, report_len );
1167 if (report_id || broken( !ret ))
1169 ok( !ret, "HidD_SetOutputReport succeeded, last error %u\n", GetLastError() );
1170 ok( GetLastError() == ERROR_INVALID_PARAMETER || broken( GetLastError() == ERROR_CRC ),
1171 "HidD_SetOutputReport returned error %u\n", GetLastError() );
1173 else
1175 ok( ret, "HidD_SetOutputReport failed, last error %u\n", GetLastError() );
1178 set_hid_expect( file, expect, sizeof(expect) );
1180 SetLastError( 0xdeadbeef );
1181 ret = HidD_SetOutputReport( file, report, report_len );
1182 ok( ret, "HidD_SetOutputReport failed, last error %u\n", GetLastError() );
1184 length = report_len * 2;
1185 SetLastError( 0xdeadbeef );
1186 ret = sync_ioctl( file, IOCTL_HID_SET_OUTPUT_REPORT, NULL, 0, report, &length, INFINITE );
1187 ok( !ret, "IOCTL_HID_SET_OUTPUT_REPORT succeeded\n" );
1188 ok( GetLastError() == ERROR_INVALID_USER_BUFFER,
1189 "IOCTL_HID_SET_OUTPUT_REPORT returned error %u\n", GetLastError() );
1190 length = 0;
1191 SetLastError( 0xdeadbeef );
1192 ret = sync_ioctl( file, IOCTL_HID_SET_OUTPUT_REPORT, report, report_len * 2, NULL, &length, INFINITE );
1193 ok( ret, "IOCTL_HID_SET_OUTPUT_REPORT failed, last error %u\n", GetLastError() );
1194 ok( length == 3, "got length %u, expected 3\n", length );
1196 set_hid_expect( file, NULL, 0 );
1199 static void test_write_file( HANDLE file, int report_id, ULONG report_len )
1201 struct hid_expect expect =
1203 .code = IOCTL_HID_WRITE_REPORT,
1204 .report_id = report_id,
1205 .report_len = report_len - (report_id ? 0 : 1),
1206 .report_buf = {report_id ? report_id : 0xcd,0xcd,0xcd,0xcd,0xcd},
1207 .ret_length = 3,
1208 .ret_status = STATUS_SUCCESS,
1211 char report[200];
1212 ULONG length;
1213 BOOL ret;
1215 SetLastError( 0xdeadbeef );
1216 ret = WriteFile( file, report, 0, &length, NULL );
1217 ok( !ret, "WriteFile succeeded\n" );
1218 ok( GetLastError() == ERROR_INVALID_USER_BUFFER, "WriteFile returned error %u\n", GetLastError() );
1219 ok( length == 0, "WriteFile returned %x\n", length );
1220 SetLastError( 0xdeadbeef );
1221 ret = WriteFile( file, report, report_len - 1, &length, NULL );
1222 ok( !ret, "WriteFile succeeded\n" );
1223 ok( GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_INVALID_USER_BUFFER,
1224 "WriteFile returned error %u\n", GetLastError() );
1225 ok( length == 0, "WriteFile returned %x\n", length );
1227 set_hid_expect( file, &expect, sizeof(expect) );
1229 memset( report, 0xcd, sizeof(report) );
1230 report[0] = 0xa5;
1231 SetLastError( 0xdeadbeef );
1232 ret = WriteFile( file, report, report_len * 2, &length, NULL );
1233 if (report_id || broken( !ret ) /* w7u */)
1235 ok( !ret, "WriteFile succeeded\n" );
1236 ok( GetLastError() == ERROR_INVALID_PARAMETER, "WriteFile returned error %u\n", GetLastError() );
1237 ok( length == 0, "WriteFile wrote %u\n", length );
1238 SetLastError( 0xdeadbeef );
1239 report[0] = report_id;
1240 ret = WriteFile( file, report, report_len, &length, NULL );
1243 if (report_id)
1245 ok( ret, "WriteFile failed, last error %u\n", GetLastError() );
1246 ok( length == 2, "WriteFile wrote %u\n", length );
1248 else
1250 ok( ret, "WriteFile failed, last error %u\n", GetLastError() );
1251 ok( length == 3, "WriteFile wrote %u\n", length );
1254 set_hid_expect( file, NULL, 0 );
1257 static void test_hidp( HANDLE file, HANDLE async_file, int report_id, BOOL polled, const HIDP_CAPS *expect_caps )
1259 const HIDP_BUTTON_CAPS expect_button_caps[] =
1262 .UsagePage = HID_USAGE_PAGE_BUTTON,
1263 .ReportID = report_id,
1264 .BitField = 2,
1265 .LinkUsage = HID_USAGE_GENERIC_JOYSTICK,
1266 .LinkUsagePage = HID_USAGE_PAGE_GENERIC,
1267 .LinkCollection = 1,
1268 .IsRange = TRUE,
1269 .IsAbsolute = TRUE,
1270 .Range.UsageMin = 1,
1271 .Range.UsageMax = 8,
1272 .Range.DataIndexMin = 2,
1273 .Range.DataIndexMax = 9,
1276 .UsagePage = HID_USAGE_PAGE_BUTTON,
1277 .ReportID = report_id,
1278 .BitField = 3,
1279 .LinkCollection = 1,
1280 .LinkUsage = HID_USAGE_GENERIC_JOYSTICK,
1281 .LinkUsagePage = HID_USAGE_PAGE_GENERIC,
1282 .IsRange = TRUE,
1283 .IsAbsolute = TRUE,
1284 .Range.UsageMin = 0x18,
1285 .Range.UsageMax = 0x1f,
1286 .Range.DataIndexMin = 10,
1287 .Range.DataIndexMax = 17,
1290 .UsagePage = HID_USAGE_PAGE_KEYBOARD,
1291 .ReportID = report_id,
1292 .BitField = 0x1fc,
1293 .LinkCollection = 1,
1294 .LinkUsage = HID_USAGE_GENERIC_JOYSTICK,
1295 .LinkUsagePage = HID_USAGE_PAGE_GENERIC,
1296 .IsRange = TRUE,
1297 .IsAbsolute = FALSE,
1298 .Range.UsageMin = 0x8,
1299 .Range.UsageMax = 0xf,
1300 .Range.DataIndexMin = 18,
1301 .Range.DataIndexMax = 25,
1304 .UsagePage = HID_USAGE_PAGE_BUTTON,
1305 .ReportID = report_id,
1306 .BitField = 2,
1307 .LinkCollection = 1,
1308 .LinkUsage = HID_USAGE_GENERIC_JOYSTICK,
1309 .LinkUsagePage = HID_USAGE_PAGE_GENERIC,
1310 .IsRange = FALSE,
1311 .IsAbsolute = TRUE,
1312 .NotRange.Usage = 0x20,
1313 .NotRange.Reserved1 = 0x20,
1314 .NotRange.DataIndex = 26,
1315 .NotRange.Reserved4 = 26,
1318 const HIDP_VALUE_CAPS expect_value_caps[] =
1321 .UsagePage = HID_USAGE_PAGE_GENERIC,
1322 .ReportID = report_id,
1323 .BitField = 2,
1324 .LinkUsage = HID_USAGE_GENERIC_JOYSTICK,
1325 .LinkUsagePage = HID_USAGE_PAGE_GENERIC,
1326 .LinkCollection = 1,
1327 .IsAbsolute = TRUE,
1328 .BitSize = 8,
1329 .ReportCount = 1,
1330 .LogicalMin = -128,
1331 .LogicalMax = 127,
1332 .NotRange.Usage = HID_USAGE_GENERIC_Y,
1333 .NotRange.Reserved1 = HID_USAGE_GENERIC_Y,
1336 .UsagePage = HID_USAGE_PAGE_GENERIC,
1337 .ReportID = report_id,
1338 .BitField = 2,
1339 .LinkUsage = HID_USAGE_GENERIC_JOYSTICK,
1340 .LinkUsagePage = HID_USAGE_PAGE_GENERIC,
1341 .LinkCollection = 1,
1342 .IsAbsolute = TRUE,
1343 .BitSize = 8,
1344 .ReportCount = 1,
1345 .LogicalMin = -128,
1346 .LogicalMax = 127,
1347 .NotRange.Usage = HID_USAGE_GENERIC_X,
1348 .NotRange.Reserved1 = HID_USAGE_GENERIC_X,
1349 .NotRange.DataIndex = 1,
1350 .NotRange.Reserved4 = 1,
1353 .UsagePage = HID_USAGE_PAGE_BUTTON,
1354 .ReportID = report_id,
1355 .BitField = 2,
1356 .LinkUsage = HID_USAGE_GENERIC_JOYSTICK,
1357 .LinkUsagePage = HID_USAGE_PAGE_GENERIC,
1358 .LinkCollection = 1,
1359 .IsAbsolute = TRUE,
1360 .ReportCount = 1,
1361 .LogicalMax = 1,
1362 .IsRange = TRUE,
1363 .Range.UsageMin = 0x21,
1364 .Range.UsageMax = 0x22,
1365 .Range.DataIndexMin = 27,
1366 .Range.DataIndexMax = 28,
1369 .UsagePage = HID_USAGE_PAGE_GENERIC,
1370 .ReportID = report_id,
1371 .BitField = 2,
1372 .LinkUsage = HID_USAGE_GENERIC_JOYSTICK,
1373 .LinkUsagePage = HID_USAGE_PAGE_GENERIC,
1374 .LinkCollection = 1,
1375 .IsAbsolute = TRUE,
1376 .BitSize = 4,
1377 .ReportCount = 2,
1378 .LogicalMin = 1,
1379 .LogicalMax = 8,
1380 .NotRange.Usage = HID_USAGE_GENERIC_HATSWITCH,
1381 .NotRange.Reserved1 = HID_USAGE_GENERIC_HATSWITCH,
1382 .NotRange.DataIndex = 29,
1383 .NotRange.Reserved4 = 29,
1386 static const HIDP_LINK_COLLECTION_NODE expect_collections[] =
1389 .LinkUsage = HID_USAGE_GENERIC_JOYSTICK,
1390 .LinkUsagePage = HID_USAGE_PAGE_GENERIC,
1391 .CollectionType = 1,
1392 .NumberOfChildren = 7,
1393 .FirstChild = 9,
1396 .LinkUsage = HID_USAGE_GENERIC_JOYSTICK,
1397 .LinkUsagePage = HID_USAGE_PAGE_GENERIC,
1398 .CollectionType = 2,
1401 static const HIDP_DATA expect_data[] =
1403 { .DataIndex = 0, },
1404 { .DataIndex = 1, },
1405 { .DataIndex = 5, .RawValue = 1, },
1406 { .DataIndex = 7, .RawValue = 1, },
1407 { .DataIndex = 19, .RawValue = 1, },
1408 { .DataIndex = 21, .RawValue = 1, },
1409 { .DataIndex = 30, },
1410 { .DataIndex = 31, },
1411 { .DataIndex = 32, .RawValue = 0xfeedcafe, },
1412 { .DataIndex = 37, .RawValue = 1, },
1413 { .DataIndex = 39, .RawValue = 1, },
1416 OVERLAPPED overlapped = {0}, overlapped2 = {0};
1417 HIDP_LINK_COLLECTION_NODE collections[16];
1418 PHIDP_PREPARSED_DATA preparsed_data;
1419 USAGE_AND_PAGE usage_and_pages[16];
1420 HIDP_BUTTON_CAPS button_caps[32];
1421 HIDP_VALUE_CAPS value_caps[16];
1422 char buffer[200], report[200];
1423 DWORD collection_count;
1424 DWORD waveform_list;
1425 HIDP_DATA data[64];
1426 USAGE usages[16];
1427 ULONG off, value;
1428 NTSTATUS status;
1429 HIDP_CAPS caps;
1430 unsigned int i;
1431 USHORT count;
1432 BOOL ret;
1434 ret = HidD_GetPreparsedData( file, &preparsed_data );
1435 ok( ret, "HidD_GetPreparsedData failed with error %u\n", GetLastError() );
1437 memset( buffer, 0, sizeof(buffer) );
1438 status = HidP_GetCaps( (PHIDP_PREPARSED_DATA)buffer, &caps );
1439 ok( status == HIDP_STATUS_INVALID_PREPARSED_DATA, "HidP_GetCaps returned %#x\n", status );
1440 status = HidP_GetCaps( preparsed_data, &caps );
1441 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetCaps returned %#x\n", status );
1442 check_hidp_caps( &caps, expect_caps );
1444 collection_count = 0;
1445 status = HidP_GetLinkCollectionNodes( collections, &collection_count, preparsed_data );
1446 ok( status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_GetLinkCollectionNodes returned %#x\n", status );
1447 ok( collection_count == caps.NumberLinkCollectionNodes,
1448 "got %d collection nodes, expected %d\n", collection_count, caps.NumberLinkCollectionNodes );
1449 collection_count = ARRAY_SIZE(collections);
1450 status = HidP_GetLinkCollectionNodes( collections, &collection_count, (PHIDP_PREPARSED_DATA)buffer );
1451 ok( status == HIDP_STATUS_INVALID_PREPARSED_DATA, "HidP_GetLinkCollectionNodes returned %#x\n", status );
1452 status = HidP_GetLinkCollectionNodes( collections, &collection_count, preparsed_data );
1453 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetLinkCollectionNodes returned %#x\n", status );
1454 ok( collection_count == caps.NumberLinkCollectionNodes,
1455 "got %d collection nodes, expected %d\n", collection_count, caps.NumberLinkCollectionNodes );
1457 for (i = 0; i < ARRAY_SIZE(expect_collections); ++i)
1459 winetest_push_context( "collections[%d]", i );
1460 check_hidp_link_collection_node( &collections[i], &expect_collections[i] );
1461 winetest_pop_context();
1464 count = ARRAY_SIZE(button_caps);
1465 status = HidP_GetButtonCaps( HidP_Output, button_caps, &count, preparsed_data );
1466 ok( status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetButtonCaps returned %#x\n", status );
1467 status = HidP_GetButtonCaps( HidP_Feature + 1, button_caps, &count, preparsed_data );
1468 ok( status == HIDP_STATUS_INVALID_REPORT_TYPE, "HidP_GetButtonCaps returned %#x\n", status );
1469 count = 0;
1470 status = HidP_GetButtonCaps( HidP_Input, button_caps, &count, preparsed_data );
1471 ok( status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_GetButtonCaps returned %#x\n", status );
1472 ok( count == caps.NumberInputButtonCaps, "HidP_GetButtonCaps returned count %d, expected %d\n",
1473 count, caps.NumberInputButtonCaps );
1474 count = ARRAY_SIZE(button_caps);
1475 status = HidP_GetButtonCaps( HidP_Input, button_caps, &count, (PHIDP_PREPARSED_DATA)buffer );
1476 ok( status == HIDP_STATUS_INVALID_PREPARSED_DATA, "HidP_GetButtonCaps returned %#x\n", status );
1477 memset( button_caps, 0, sizeof(button_caps) );
1478 status = HidP_GetButtonCaps( HidP_Input, button_caps, &count, preparsed_data );
1479 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetButtonCaps returned %#x\n", status );
1480 ok( count == caps.NumberInputButtonCaps, "HidP_GetButtonCaps returned count %d, expected %d\n",
1481 count, caps.NumberInputButtonCaps );
1483 for (i = 0; i < ARRAY_SIZE(expect_button_caps); ++i)
1485 winetest_push_context( "button_caps[%d]", i );
1486 check_hidp_button_caps( &button_caps[i], &expect_button_caps[i] );
1487 winetest_pop_context();
1490 count = ARRAY_SIZE(button_caps) - 1;
1491 status = HidP_GetSpecificButtonCaps( HidP_Output, 0, 0, 0, button_caps, &count, preparsed_data );
1492 ok( status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetSpecificButtonCaps returned %#x\n", status );
1493 status = HidP_GetSpecificButtonCaps( HidP_Feature + 1, 0, 0, 0, button_caps, &count, preparsed_data );
1494 ok( status == HIDP_STATUS_INVALID_REPORT_TYPE, "HidP_GetSpecificButtonCaps returned %#x\n", status );
1495 count = 0;
1496 status = HidP_GetSpecificButtonCaps( HidP_Input, 0, 0, 0, button_caps, &count, preparsed_data );
1497 ok( status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_GetSpecificButtonCaps returned %#x\n", status );
1498 ok( count == caps.NumberInputButtonCaps, "HidP_GetSpecificButtonCaps returned count %d, expected %d\n",
1499 count, caps.NumberInputButtonCaps );
1500 count = ARRAY_SIZE(button_caps) - 1;
1501 status = HidP_GetSpecificButtonCaps( HidP_Input, 0, 0, 0, button_caps, &count, (PHIDP_PREPARSED_DATA)buffer );
1502 ok( status == HIDP_STATUS_INVALID_PREPARSED_DATA, "HidP_GetSpecificButtonCaps returned %#x\n", status );
1504 status = HidP_GetSpecificButtonCaps( HidP_Input, 0, 0, 0, button_caps + 1, &count, preparsed_data );
1505 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetSpecificButtonCaps returned %#x\n", status );
1506 ok( count == caps.NumberInputButtonCaps, "HidP_GetSpecificButtonCaps returned count %d, expected %d\n",
1507 count, caps.NumberInputButtonCaps );
1508 check_hidp_button_caps( &button_caps[1], &button_caps[0] );
1510 status = HidP_GetSpecificButtonCaps( HidP_Input, HID_USAGE_PAGE_BUTTON, 0, 5, button_caps + 1,
1511 &count, preparsed_data );
1512 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetSpecificButtonCaps returned %#x\n", status );
1513 ok( count == 1, "HidP_GetSpecificButtonCaps returned count %d, expected %d\n", count, 1 );
1514 check_hidp_button_caps( &button_caps[1], &button_caps[0] );
1516 count = 0xbeef;
1517 status = HidP_GetSpecificButtonCaps( HidP_Input, 0xfffe, 0, 0, button_caps, &count, preparsed_data );
1518 ok( status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetSpecificButtonCaps returned %#x\n", status );
1519 ok( count == 0, "HidP_GetSpecificButtonCaps returned count %d, expected %d\n", count, 0 );
1520 count = 0xbeef;
1521 status = HidP_GetSpecificButtonCaps( HidP_Input, 0, 0xfffe, 0, button_caps, &count, preparsed_data );
1522 ok( status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetSpecificButtonCaps returned %#x\n", status );
1523 ok( count == 0, "HidP_GetSpecificButtonCaps returned count %d, expected %d\n", count, 0 );
1524 count = 0xbeef;
1525 status = HidP_GetSpecificButtonCaps( HidP_Input, 0, 0, 0xfffe, button_caps, &count, preparsed_data );
1526 ok( status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetSpecificButtonCaps returned %#x\n", status );
1527 ok( count == 0, "HidP_GetSpecificButtonCaps returned count %d, expected %d\n", count, 0 );
1529 count = ARRAY_SIZE(value_caps);
1530 status = HidP_GetValueCaps( HidP_Output, value_caps, &count, preparsed_data );
1531 ok( status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetValueCaps returned %#x\n", status );
1532 status = HidP_GetValueCaps( HidP_Feature + 1, value_caps, &count, preparsed_data );
1533 ok( status == HIDP_STATUS_INVALID_REPORT_TYPE, "HidP_GetValueCaps returned %#x\n", status );
1534 count = 0;
1535 status = HidP_GetValueCaps( HidP_Input, value_caps, &count, preparsed_data );
1536 ok( status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_GetValueCaps returned %#x\n", status );
1537 ok( count == caps.NumberInputValueCaps, "HidP_GetValueCaps returned count %d, expected %d\n",
1538 count, caps.NumberInputValueCaps );
1539 count = ARRAY_SIZE(value_caps);
1540 status = HidP_GetValueCaps( HidP_Input, value_caps, &count, (PHIDP_PREPARSED_DATA)buffer );
1541 ok( status == HIDP_STATUS_INVALID_PREPARSED_DATA, "HidP_GetValueCaps returned %#x\n", status );
1542 status = HidP_GetValueCaps( HidP_Input, value_caps, &count, preparsed_data );
1543 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetValueCaps returned %#x\n", status );
1544 ok( count == caps.NumberInputValueCaps, "HidP_GetValueCaps returned count %d, expected %d\n",
1545 count, caps.NumberInputValueCaps );
1547 for (i = 0; i < ARRAY_SIZE(expect_value_caps); ++i)
1549 winetest_push_context( "value_caps[%d]", i );
1550 check_hidp_value_caps( &value_caps[i], &expect_value_caps[i] );
1551 winetest_pop_context();
1554 count = ARRAY_SIZE(value_caps) - 4;
1555 status = HidP_GetSpecificValueCaps( HidP_Output, 0, 0, 0, value_caps, &count, preparsed_data );
1556 ok( status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetSpecificValueCaps returned %#x\n", status );
1557 status = HidP_GetSpecificValueCaps( HidP_Feature + 1, 0, 0, 0, value_caps, &count, preparsed_data );
1558 ok( status == HIDP_STATUS_INVALID_REPORT_TYPE, "HidP_GetSpecificValueCaps returned %#x\n", status );
1559 count = 0;
1560 status = HidP_GetSpecificValueCaps( HidP_Input, 0, 0, 0, value_caps, &count, preparsed_data );
1561 ok( status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_GetSpecificValueCaps returned %#x\n", status );
1562 ok( count == caps.NumberInputValueCaps, "HidP_GetSpecificValueCaps returned count %d, expected %d\n",
1563 count, caps.NumberInputValueCaps );
1564 count = ARRAY_SIZE(value_caps) - 4;
1565 status = HidP_GetSpecificValueCaps( HidP_Input, 0, 0, 0, value_caps + 4, &count, (PHIDP_PREPARSED_DATA)buffer );
1566 ok( status == HIDP_STATUS_INVALID_PREPARSED_DATA, "HidP_GetSpecificValueCaps returned %#x\n", status );
1568 status = HidP_GetSpecificValueCaps( HidP_Input, 0, 0, 0, value_caps + 4, &count, preparsed_data );
1569 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetSpecificValueCaps returned %#x\n", status );
1570 ok( count == caps.NumberInputValueCaps, "HidP_GetSpecificValueCaps returned count %d, expected %d\n",
1571 count, caps.NumberInputValueCaps );
1572 check_hidp_value_caps( &value_caps[4], &value_caps[0] );
1573 check_hidp_value_caps( &value_caps[5], &value_caps[1] );
1574 check_hidp_value_caps( &value_caps[6], &value_caps[2] );
1575 check_hidp_value_caps( &value_caps[7], &value_caps[3] );
1577 count = 1;
1578 status = HidP_GetSpecificValueCaps( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_HATSWITCH,
1579 value_caps + 4, &count, preparsed_data );
1580 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetSpecificValueCaps returned %#x\n", status );
1581 ok( count == 1, "HidP_GetSpecificValueCaps returned count %d, expected %d\n", count, 1 );
1582 check_hidp_value_caps( &value_caps[4], &value_caps[3] );
1584 count = 0xdead;
1585 status = HidP_GetSpecificValueCaps( HidP_Input, 0xfffe, 0, 0, value_caps, &count, preparsed_data );
1586 ok( status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetSpecificValueCaps returned %#x\n", status );
1587 ok( count == 0, "HidP_GetSpecificValueCaps returned count %d, expected %d\n", count, 0 );
1588 count = 0xdead;
1589 status = HidP_GetSpecificValueCaps( HidP_Input, 0, 0xfffe, 0, value_caps, &count, preparsed_data );
1590 ok( status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetSpecificValueCaps returned %#x\n", status );
1591 ok( count == 0, "HidP_GetSpecificValueCaps returned count %d, expected %d\n", count, 0 );
1592 count = 0xdead;
1593 status = HidP_GetSpecificValueCaps( HidP_Input, 0, 0, 0xfffe, value_caps, &count, preparsed_data );
1594 ok( status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetSpecificValueCaps returned %#x\n", status );
1595 ok( count == 0, "HidP_GetSpecificValueCaps returned count %d, expected %d\n", count, 0 );
1597 status = HidP_InitializeReportForID( HidP_Input, 0, (PHIDP_PREPARSED_DATA)buffer, report, sizeof(report) );
1598 ok( status == HIDP_STATUS_INVALID_PREPARSED_DATA, "HidP_InitializeReportForID returned %#x\n", status );
1599 status = HidP_InitializeReportForID( HidP_Feature + 1, 0, preparsed_data, report, sizeof(report) );
1600 ok( status == HIDP_STATUS_INVALID_REPORT_TYPE, "HidP_InitializeReportForID returned %#x\n", status );
1601 status = HidP_InitializeReportForID( HidP_Input, 0, preparsed_data, report, sizeof(report) );
1602 ok( status == HIDP_STATUS_INVALID_REPORT_LENGTH, "HidP_InitializeReportForID returned %#x\n", status );
1603 status = HidP_InitializeReportForID( HidP_Input, 0, preparsed_data, report, caps.InputReportByteLength + 1 );
1604 ok( status == HIDP_STATUS_INVALID_REPORT_LENGTH, "HidP_InitializeReportForID returned %#x\n", status );
1605 status = HidP_InitializeReportForID( HidP_Input, 1 - report_id, preparsed_data, report,
1606 caps.InputReportByteLength );
1607 ok( status == HIDP_STATUS_REPORT_DOES_NOT_EXIST, "HidP_InitializeReportForID returned %#x\n", status );
1609 memset( report, 0xcd, sizeof(report) );
1610 status = HidP_InitializeReportForID( HidP_Input, report_id, preparsed_data, report, caps.InputReportByteLength );
1611 ok( status == HIDP_STATUS_SUCCESS, "HidP_InitializeReportForID returned %#x\n", status );
1613 memset( buffer, 0xcd, sizeof(buffer) );
1614 memset( buffer, 0, caps.InputReportByteLength );
1615 buffer[0] = report_id;
1616 ok( !memcmp( buffer, report, sizeof(buffer) ), "unexpected report data\n" );
1618 status = HidP_SetUsageValueArray( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_X, buffer,
1619 sizeof(buffer), preparsed_data, report, caps.InputReportByteLength );
1620 ok( status == HIDP_STATUS_NOT_VALUE_ARRAY, "HidP_SetUsageValueArray returned %#x\n", status );
1621 memset( buffer, 0xcd, sizeof(buffer) );
1622 status = HidP_SetUsageValueArray( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_HATSWITCH,
1623 buffer, 0, preparsed_data, report, caps.InputReportByteLength );
1624 ok( status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_SetUsageValueArray returned %#x\n", status );
1625 status = HidP_SetUsageValueArray( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_HATSWITCH,
1626 buffer, 8, preparsed_data, report, caps.InputReportByteLength );
1627 todo_wine
1628 ok( status == HIDP_STATUS_NOT_IMPLEMENTED, "HidP_SetUsageValueArray returned %#x\n", status );
1630 status = HidP_GetUsageValueArray( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_X, buffer,
1631 sizeof(buffer), preparsed_data, report, caps.InputReportByteLength );
1632 ok( status == HIDP_STATUS_NOT_VALUE_ARRAY, "HidP_GetUsageValueArray returned %#x\n", status );
1633 memset( buffer, 0xcd, sizeof(buffer) );
1634 status = HidP_GetUsageValueArray( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_HATSWITCH,
1635 buffer, 0, preparsed_data, report, caps.InputReportByteLength );
1636 ok( status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_GetUsageValueArray returned %#x\n", status );
1637 status = HidP_GetUsageValueArray( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_HATSWITCH,
1638 buffer, 8, preparsed_data, report, caps.InputReportByteLength );
1639 todo_wine
1640 ok( status == HIDP_STATUS_NOT_IMPLEMENTED, "HidP_GetUsageValueArray returned %#x\n", status );
1642 value = -128;
1643 status = HidP_SetUsageValue( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_X, value,
1644 preparsed_data, report, caps.InputReportByteLength );
1645 ok( status == HIDP_STATUS_SUCCESS, "HidP_SetUsageValue returned %#x\n", status );
1646 value = 0xdeadbeef;
1647 status = HidP_GetUsageValue( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_X, &value,
1648 preparsed_data, report, caps.InputReportByteLength );
1649 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetUsageValue returned %#x\n", status );
1650 ok( value == 0x80, "got value %x, expected %#x\n", value, 0x80 );
1651 value = 0xdeadbeef;
1652 status = HidP_GetScaledUsageValue( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_X,
1653 (LONG *)&value, preparsed_data, report, caps.InputReportByteLength );
1654 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetScaledUsageValue returned %#x\n", status );
1655 ok( value == -128, "got value %x, expected %#x\n", value, -128 );
1657 value = 127;
1658 status = HidP_SetUsageValue( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_X, value,
1659 preparsed_data, report, caps.InputReportByteLength );
1660 ok( status == HIDP_STATUS_SUCCESS, "HidP_SetUsageValue returned %#x\n", status );
1661 value = 0xdeadbeef;
1662 status = HidP_GetScaledUsageValue( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_X,
1663 (LONG *)&value, preparsed_data, report, caps.InputReportByteLength );
1664 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetScaledUsageValue returned %#x\n", status );
1665 ok( value == 127, "got value %x, expected %#x\n", value, 127 );
1667 value = 0;
1668 status = HidP_SetUsageValue( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_X, value,
1669 preparsed_data, report, caps.InputReportByteLength );
1670 ok( status == HIDP_STATUS_SUCCESS, "HidP_SetUsageValue returned %#x\n", status );
1671 value = 0xdeadbeef;
1672 status = HidP_GetScaledUsageValue( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_X,
1673 (LONG *)&value, preparsed_data, report, caps.InputReportByteLength );
1674 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetScaledUsageValue returned %#x\n", status );
1675 ok( value == 0, "got value %x, expected %#x\n", value, 0 );
1677 value = 0x7fffffff;
1678 status = HidP_SetUsageValue( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z, value,
1679 preparsed_data, report, caps.InputReportByteLength );
1680 ok( status == HIDP_STATUS_SUCCESS, "HidP_SetUsageValue returned %#x\n", status );
1681 value = 0xdeadbeef;
1682 status = HidP_GetScaledUsageValue( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
1683 (LONG *)&value, preparsed_data, report, caps.InputReportByteLength );
1684 ok( status == HIDP_STATUS_VALUE_OUT_OF_RANGE, "HidP_GetScaledUsageValue returned %#x\n", status );
1685 ok( value == 0, "got value %x, expected %#x\n", value, 0 );
1686 value = 0xdeadbeef;
1687 status = HidP_GetUsageValue( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z, &value,
1688 preparsed_data, report, caps.InputReportByteLength );
1689 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetUsageValue returned %#x\n", status );
1690 ok( value == 0x7fffffff, "got value %x, expected %#x\n", value, 0x7fffffff );
1692 value = 0x3fffffff;
1693 status = HidP_SetUsageValue( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z, value,
1694 preparsed_data, report, caps.InputReportByteLength );
1695 ok( status == HIDP_STATUS_SUCCESS, "HidP_SetUsageValue returned %#x\n", status );
1696 value = 0xdeadbeef;
1697 status = HidP_GetScaledUsageValue( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
1698 (LONG *)&value, preparsed_data, report, caps.InputReportByteLength );
1699 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetScaledUsageValue returned %#x\n", status );
1700 ok( value == 0x7fffffff, "got value %x, expected %#x\n", value, 0x7fffffff );
1702 value = 0;
1703 status = HidP_SetUsageValue( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z, value,
1704 preparsed_data, report, caps.InputReportByteLength );
1705 ok( status == HIDP_STATUS_SUCCESS, "HidP_SetUsageValue returned %#x\n", status );
1706 value = 0xdeadbeef;
1707 status = HidP_GetScaledUsageValue( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
1708 (LONG *)&value, preparsed_data, report, caps.InputReportByteLength );
1709 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetScaledUsageValue returned %#x\n", status );
1710 ok( value == 0x80000000, "got value %x, expected %#x\n", value, 0x80000000 );
1712 value = 0;
1713 status = HidP_SetUsageValue( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_RX, value,
1714 preparsed_data, report, caps.InputReportByteLength );
1715 ok( status == HIDP_STATUS_SUCCESS, "HidP_SetUsageValue returned %#x\n", status );
1716 value = 0xdeadbeef;
1717 status = HidP_GetScaledUsageValue( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_RX,
1718 (LONG *)&value, preparsed_data, report, caps.InputReportByteLength );
1719 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetScaledUsageValue returned %#x\n", status );
1720 ok( value == 0, "got value %x, expected %#x\n", value, 0 );
1722 value = 0xfeedcafe;
1723 status = HidP_SetUsageValue( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_RY, value,
1724 preparsed_data, report, caps.InputReportByteLength );
1725 ok( status == HIDP_STATUS_SUCCESS, "HidP_SetUsageValue returned %#x\n", status );
1726 value = 0xdeadbeef;
1727 status = HidP_GetScaledUsageValue( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_RY,
1728 (LONG *)&value, preparsed_data, report, caps.InputReportByteLength );
1729 ok( status == HIDP_STATUS_BAD_LOG_PHY_VALUES, "HidP_GetScaledUsageValue returned %#x\n", status );
1730 ok( value == 0, "got value %x, expected %#x\n", value, 0 );
1731 status = HidP_SetScaledUsageValue( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_RY,
1732 0, preparsed_data, report, caps.InputReportByteLength );
1733 ok( status == HIDP_STATUS_BAD_LOG_PHY_VALUES, "HidP_GetScaledUsageValue returned %#x\n", status );
1734 ok( value == 0, "got value %x, expected %#x\n", value, 0 );
1736 value = HidP_MaxUsageListLength( HidP_Feature + 1, 0, preparsed_data );
1737 ok( value == 0, "HidP_MaxUsageListLength(HidP_Feature + 1, 0) returned %d, expected %d\n", value, 0 );
1738 value = HidP_MaxUsageListLength( HidP_Input, 0, preparsed_data );
1739 ok( value == 50, "HidP_MaxUsageListLength(HidP_Input, 0) returned %d, expected %d\n", value, 50 );
1740 value = HidP_MaxUsageListLength( HidP_Input, HID_USAGE_PAGE_BUTTON, preparsed_data );
1741 ok( value == 32, "HidP_MaxUsageListLength(HidP_Input, HID_USAGE_PAGE_BUTTON) returned %d, expected %d\n",
1742 value, 32 );
1743 value = HidP_MaxUsageListLength( HidP_Input, HID_USAGE_PAGE_LED, preparsed_data );
1744 ok( value == 8, "HidP_MaxUsageListLength(HidP_Input, HID_USAGE_PAGE_LED) returned %d, expected %d\n",
1745 value, 8 );
1746 value = HidP_MaxUsageListLength( HidP_Feature, HID_USAGE_PAGE_BUTTON, preparsed_data );
1747 ok( value == 8, "HidP_MaxUsageListLength(HidP_Feature, HID_USAGE_PAGE_BUTTON) returned %d, expected %d\n",
1748 value, 8 );
1749 value = HidP_MaxUsageListLength( HidP_Feature, HID_USAGE_PAGE_LED, preparsed_data );
1750 ok( value == 0, "HidP_MaxUsageListLength(HidP_Feature, HID_USAGE_PAGE_LED) returned %d, expected %d\n",
1751 value, 0 );
1753 usages[0] = 0xff;
1754 value = 1;
1755 status = HidP_SetUsages( HidP_Input, HID_USAGE_PAGE_BUTTON, 0, usages, &value, preparsed_data,
1756 report, caps.InputReportByteLength );
1757 ok( status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_SetUsages returned %#x\n", status );
1758 usages[1] = 2;
1759 usages[2] = 0xff;
1760 value = 3;
1761 status = HidP_SetUsages( HidP_Input, HID_USAGE_PAGE_BUTTON, 0, usages, &value, preparsed_data,
1762 report, caps.InputReportByteLength );
1763 ok( status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_SetUsages returned %#x\n", status );
1764 usages[0] = 4;
1765 usages[1] = 6;
1766 value = 2;
1767 status = HidP_SetUsages( HidP_Input, HID_USAGE_PAGE_BUTTON, 0, usages, &value, preparsed_data,
1768 report, caps.InputReportByteLength );
1769 ok( status == HIDP_STATUS_SUCCESS, "HidP_SetUsages returned %#x\n", status );
1770 usages[0] = 4;
1771 usages[1] = 6;
1772 value = 2;
1773 status = HidP_SetUsages( HidP_Input, HID_USAGE_PAGE_LED, 0, usages, &value, preparsed_data,
1774 report, caps.InputReportByteLength );
1775 ok( status == HIDP_STATUS_SUCCESS, "HidP_SetUsages returned %#x\n", status );
1777 value = ARRAY_SIZE(usages);
1778 status = HidP_GetUsages( HidP_Input, HID_USAGE_PAGE_KEYBOARD, 0, usages, &value, preparsed_data,
1779 report, caps.InputReportByteLength );
1780 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetUsages returned %#x\n", status );
1781 ok( value == 0, "got usage count %d, expected %d\n", value, 2 );
1783 usages[0] = 0x9;
1784 usages[1] = 0xb;
1785 usages[2] = 0xa;
1786 value = 3;
1787 ok( report[6] == 0, "got report[6] %x expected 0\n", report[6] );
1788 ok( report[7] == 0, "got report[7] %x expected 0\n", report[7] );
1789 memcpy( buffer, report, caps.InputReportByteLength );
1790 status = HidP_SetUsages( HidP_Input, HID_USAGE_PAGE_KEYBOARD, 0, usages, &value, preparsed_data,
1791 report, caps.InputReportByteLength );
1792 ok( status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_SetUsages returned %#x\n", status );
1793 buffer[13] = 2;
1794 buffer[14] = 4;
1795 ok( !memcmp( buffer, report, caps.InputReportByteLength ), "unexpected report data\n" );
1797 status = HidP_SetUsageValue( HidP_Input, HID_USAGE_PAGE_LED, 0, 6, 1, preparsed_data, report,
1798 caps.InputReportByteLength );
1799 ok( status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_SetUsageValue returned %#x\n", status );
1801 value = 0xdeadbeef;
1802 status = HidP_GetUsageValue( HidP_Input, HID_USAGE_PAGE_LED, 0, 6, &value, preparsed_data,
1803 report, caps.InputReportByteLength );
1804 ok( status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_SetUsageValue returned %#x\n", status );
1805 ok( value == 0xdeadbeef, "got value %x, expected %#x\n", value, 0xdeadbeef );
1807 value = 1;
1808 status = HidP_GetUsages( HidP_Input, HID_USAGE_PAGE_BUTTON, 0, usages, &value, preparsed_data,
1809 report, caps.InputReportByteLength );
1810 ok( status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_GetUsages returned %#x\n", status );
1811 ok( value == 2, "got usage count %d, expected %d\n", value, 2 );
1812 value = ARRAY_SIZE(usages);
1813 memset( usages, 0xcd, sizeof(usages) );
1814 status = HidP_GetUsages( HidP_Input, HID_USAGE_PAGE_BUTTON, 0, usages, &value, preparsed_data,
1815 report, caps.InputReportByteLength );
1816 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetUsages returned %#x\n", status );
1817 ok( value == 2, "got usage count %d, expected %d\n", value, 2 );
1818 ok( usages[0] == 4, "got usages[0] %x, expected %x\n", usages[0], 4 );
1819 ok( usages[1] == 6, "got usages[1] %x, expected %x\n", usages[1], 6 );
1821 value = ARRAY_SIZE(usages);
1822 memset( usages, 0xcd, sizeof(usages) );
1823 status = HidP_GetUsages( HidP_Input, HID_USAGE_PAGE_LED, 0, usages, &value, preparsed_data,
1824 report, caps.InputReportByteLength );
1825 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetUsages returned %#x\n", status );
1826 ok( value == 2, "got usage count %d, expected %d\n", value, 2 );
1827 ok( usages[0] == 6, "got usages[0] %x, expected %x\n", usages[0], 6 );
1828 ok( usages[1] == 4, "got usages[1] %x, expected %x\n", usages[1], 4 );
1830 value = ARRAY_SIZE(usage_and_pages);
1831 memset( usage_and_pages, 0xcd, sizeof(usage_and_pages) );
1832 status = HidP_GetUsagesEx( HidP_Input, 0, usage_and_pages, &value, preparsed_data, report,
1833 caps.InputReportByteLength );
1834 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetUsagesEx returned %#x\n", status );
1835 ok( value == 6, "got usage count %d, expected %d\n", value, 4 );
1836 ok( usage_and_pages[0].UsagePage == HID_USAGE_PAGE_BUTTON, "got usage_and_pages[0] UsagePage %x, expected %x\n",
1837 usage_and_pages[0].UsagePage, HID_USAGE_PAGE_BUTTON );
1838 ok( usage_and_pages[1].UsagePage == HID_USAGE_PAGE_BUTTON, "got usage_and_pages[1] UsagePage %x, expected %x\n",
1839 usage_and_pages[1].UsagePage, HID_USAGE_PAGE_BUTTON );
1840 ok( usage_and_pages[2].UsagePage == HID_USAGE_PAGE_KEYBOARD, "got usage_and_pages[2] UsagePage %x, expected %x\n",
1841 usage_and_pages[2].UsagePage, HID_USAGE_PAGE_KEYBOARD );
1842 ok( usage_and_pages[3].UsagePage == HID_USAGE_PAGE_KEYBOARD, "got usage_and_pages[3] UsagePage %x, expected %x\n",
1843 usage_and_pages[3].UsagePage, HID_USAGE_PAGE_KEYBOARD );
1844 ok( usage_and_pages[4].UsagePage == HID_USAGE_PAGE_LED, "got usage_and_pages[4] UsagePage %x, expected %x\n",
1845 usage_and_pages[4].UsagePage, HID_USAGE_PAGE_LED );
1846 ok( usage_and_pages[5].UsagePage == HID_USAGE_PAGE_LED, "got usage_and_pages[5] UsagePage %x, expected %x\n",
1847 usage_and_pages[5].UsagePage, HID_USAGE_PAGE_LED );
1848 ok( usage_and_pages[0].Usage == 4, "got usage_and_pages[0] Usage %x, expected %x\n",
1849 usage_and_pages[0].Usage, 4 );
1850 ok( usage_and_pages[1].Usage == 6, "got usage_and_pages[1] Usage %x, expected %x\n",
1851 usage_and_pages[1].Usage, 6 );
1852 ok( usage_and_pages[2].Usage == 9, "got usage_and_pages[2] Usage %x, expected %x\n",
1853 usage_and_pages[2].Usage, 9 );
1854 ok( usage_and_pages[3].Usage == 11, "got usage_and_pages[3] Usage %x, expected %x\n",
1855 usage_and_pages[3].Usage, 11 );
1856 ok( usage_and_pages[4].Usage == 6, "got usage_and_pages[4] Usage %x, expected %x\n",
1857 usage_and_pages[4].Usage, 6 );
1858 ok( usage_and_pages[5].Usage == 4, "got usage_and_pages[5] Usage %x, expected %x\n",
1859 usage_and_pages[5].Usage, 4 );
1861 value = HidP_MaxDataListLength( HidP_Feature + 1, preparsed_data );
1862 ok( value == 0, "HidP_MaxDataListLength(HidP_Feature + 1) returned %d, expected %d\n", value, 0 );
1863 value = HidP_MaxDataListLength( HidP_Input, preparsed_data );
1864 ok( value == 58, "HidP_MaxDataListLength(HidP_Input) returned %d, expected %d\n", value, 58 );
1865 value = HidP_MaxDataListLength( HidP_Output, preparsed_data );
1866 ok( value == 0, "HidP_MaxDataListLength(HidP_Output) returned %d, expected %d\n", value, 0 );
1867 value = HidP_MaxDataListLength( HidP_Feature, preparsed_data );
1868 ok( value == 14, "HidP_MaxDataListLength(HidP_Feature) returned %d, expected %d\n", value, 14 );
1870 value = 1;
1871 status = HidP_GetData( HidP_Input, data, &value, preparsed_data, report, caps.InputReportByteLength );
1872 ok( status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_GetData returned %#x\n", status );
1873 ok( value == 11, "got data count %d, expected %d\n", value, 11 );
1874 memset( data, 0, sizeof(data) );
1875 status = HidP_GetData( HidP_Input, data, &value, preparsed_data, report, caps.InputReportByteLength );
1876 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetData returned %#x\n", status );
1877 for (i = 0; i < ARRAY_SIZE(expect_data); ++i)
1879 winetest_push_context( "data[%d]", i );
1880 check_member( data[i], expect_data[i], "%d", DataIndex );
1881 check_member( data[i], expect_data[i], "%d", RawValue );
1882 winetest_pop_context();
1885 /* HID nary usage collections are set with 1-based usage index in their declaration order */
1887 memset( report, 0, caps.InputReportByteLength );
1888 status = HidP_InitializeReportForID( HidP_Input, report_id, preparsed_data, report, caps.InputReportByteLength );
1889 ok( status == HIDP_STATUS_SUCCESS, "HidP_InitializeReportForID returned %#x\n", status );
1890 value = 2;
1891 usages[0] = 0x8e;
1892 usages[1] = 0x8f;
1893 status = HidP_SetUsages( HidP_Input, HID_USAGE_PAGE_KEYBOARD, 0, usages, &value, preparsed_data,
1894 report, caps.InputReportByteLength );
1895 ok( status == HIDP_STATUS_SUCCESS, "HidP_SetUsages returned %#x\n", status );
1896 ok( report[caps.InputReportByteLength - 2] == 3, "unexpected usage index %d, expected 3\n",
1897 report[caps.InputReportByteLength - 2] );
1898 ok( report[caps.InputReportByteLength - 1] == 4, "unexpected usage index %d, expected 4\n",
1899 report[caps.InputReportByteLength - 1] );
1900 status = HidP_UnsetUsages( HidP_Input, HID_USAGE_PAGE_KEYBOARD, 0, usages, &value,
1901 preparsed_data, report, caps.InputReportByteLength );
1902 ok( status == HIDP_STATUS_SUCCESS, "HidP_UnsetUsages returned %#x\n", status );
1903 ok( report[caps.InputReportByteLength - 2] == 0, "unexpected usage index %d, expected 0\n",
1904 report[caps.InputReportByteLength - 2] );
1905 ok( report[caps.InputReportByteLength - 1] == 0, "unexpected usage index %d, expected 0\n",
1906 report[caps.InputReportByteLength - 1] );
1907 status = HidP_UnsetUsages( HidP_Input, HID_USAGE_PAGE_KEYBOARD, 0, usages, &value,
1908 preparsed_data, report, caps.InputReportByteLength );
1909 ok( status == HIDP_STATUS_BUTTON_NOT_PRESSED, "HidP_UnsetUsages returned %#x\n", status );
1910 value = 1;
1911 usages[0] = 0x8c;
1912 status = HidP_SetUsages( HidP_Input, HID_USAGE_PAGE_KEYBOARD, 0, usages, &value, preparsed_data,
1913 report, caps.InputReportByteLength );
1914 ok( status == HIDP_STATUS_SUCCESS, "HidP_SetUsages returned %#x\n", status );
1915 ok( report[caps.InputReportByteLength - 2] == 1, "unexpected usage index %d, expected 1\n",
1916 report[caps.InputReportByteLength - 2] );
1918 memset( report, 0xcd, sizeof(report) );
1919 status = HidP_InitializeReportForID( HidP_Feature, 3, preparsed_data, report, caps.FeatureReportByteLength );
1920 ok( status == HIDP_STATUS_REPORT_DOES_NOT_EXIST, "HidP_InitializeReportForID returned %#x\n", status );
1922 memset( report, 0xcd, sizeof(report) );
1923 status = HidP_InitializeReportForID( HidP_Feature, report_id, preparsed_data, report,
1924 caps.FeatureReportByteLength );
1925 ok( status == HIDP_STATUS_SUCCESS, "HidP_InitializeReportForID returned %#x\n", status );
1927 memset( buffer, 0xcd, sizeof(buffer) );
1928 memset( buffer, 0, caps.FeatureReportByteLength );
1929 buffer[0] = report_id;
1930 ok( !memcmp( buffer, report, sizeof(buffer) ), "unexpected report data\n" );
1932 for (i = 0; i < caps.NumberLinkCollectionNodes; ++i)
1934 if (collections[i].LinkUsagePage != HID_USAGE_PAGE_HAPTICS) continue;
1935 if (collections[i].LinkUsage == HID_USAGE_HAPTICS_WAVEFORM_LIST) break;
1937 ok( i < caps.NumberLinkCollectionNodes,
1938 "HID_USAGE_HAPTICS_WAVEFORM_LIST collection not found\n" );
1939 waveform_list = i;
1941 status = HidP_SetUsageValue( HidP_Feature, HID_USAGE_PAGE_ORDINAL, waveform_list, 3,
1942 HID_USAGE_HAPTICS_WAVEFORM_RUMBLE, (PHIDP_PREPARSED_DATA)buffer,
1943 report, caps.FeatureReportByteLength );
1944 ok( status == HIDP_STATUS_INVALID_PREPARSED_DATA, "HidP_SetUsageValue returned %#x\n", status );
1945 status = HidP_SetUsageValue( HidP_Feature + 1, HID_USAGE_PAGE_ORDINAL, waveform_list, 3,
1946 HID_USAGE_HAPTICS_WAVEFORM_RUMBLE, preparsed_data, report,
1947 caps.FeatureReportByteLength );
1948 ok( status == HIDP_STATUS_INVALID_REPORT_TYPE, "HidP_SetUsageValue returned %#x\n", status );
1949 status = HidP_SetUsageValue( HidP_Feature, HID_USAGE_PAGE_ORDINAL, waveform_list, 3,
1950 HID_USAGE_HAPTICS_WAVEFORM_RUMBLE, preparsed_data, report,
1951 caps.FeatureReportByteLength + 1 );
1952 ok( status == HIDP_STATUS_INVALID_REPORT_LENGTH, "HidP_SetUsageValue returned %#x\n", status );
1953 report[0] = 1 - report_id;
1954 status = HidP_SetUsageValue( HidP_Feature, HID_USAGE_PAGE_ORDINAL, waveform_list, 3,
1955 HID_USAGE_HAPTICS_WAVEFORM_RUMBLE, preparsed_data, report,
1956 caps.FeatureReportByteLength );
1957 ok( status == (report_id ? HIDP_STATUS_SUCCESS : HIDP_STATUS_INCOMPATIBLE_REPORT_ID),
1958 "HidP_SetUsageValue returned %#x\n", status );
1959 report[0] = 2;
1960 status = HidP_SetUsageValue( HidP_Feature, HID_USAGE_PAGE_ORDINAL, waveform_list, 3,
1961 HID_USAGE_HAPTICS_WAVEFORM_RUMBLE, preparsed_data, report,
1962 caps.FeatureReportByteLength );
1963 ok( status == HIDP_STATUS_INCOMPATIBLE_REPORT_ID, "HidP_SetUsageValue returned %#x\n", status );
1964 report[0] = report_id;
1965 status = HidP_SetUsageValue( HidP_Feature, HID_USAGE_PAGE_ORDINAL, 0xdead, 3, HID_USAGE_HAPTICS_WAVEFORM_RUMBLE,
1966 preparsed_data, report, caps.FeatureReportByteLength );
1967 ok( status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_SetUsageValue returned %#x\n", status );
1969 status = HidP_SetUsageValue( HidP_Feature, HID_USAGE_PAGE_ORDINAL, waveform_list, 3,
1970 HID_USAGE_HAPTICS_WAVEFORM_RUMBLE, preparsed_data, report,
1971 caps.FeatureReportByteLength );
1972 ok( status == HIDP_STATUS_SUCCESS, "HidP_SetUsageValue returned %#x\n", status );
1974 memset( buffer, 0xcd, sizeof(buffer) );
1975 memset( buffer, 0, caps.FeatureReportByteLength );
1976 buffer[0] = report_id;
1977 value = HID_USAGE_HAPTICS_WAVEFORM_RUMBLE;
1978 memcpy( buffer + 1, &value, 2 );
1979 ok( !memcmp( buffer, report, sizeof(buffer) ), "unexpected report data\n" );
1981 status = HidP_GetUsageValue( HidP_Feature, HID_USAGE_PAGE_ORDINAL, waveform_list, 3, &value,
1982 (PHIDP_PREPARSED_DATA)buffer, report, caps.FeatureReportByteLength );
1983 ok( status == HIDP_STATUS_INVALID_PREPARSED_DATA, "HidP_GetUsageValue returned %#x\n", status );
1984 status = HidP_GetUsageValue( HidP_Feature + 1, HID_USAGE_PAGE_ORDINAL, waveform_list, 3, &value,
1985 preparsed_data, report, caps.FeatureReportByteLength );
1986 ok( status == HIDP_STATUS_INVALID_REPORT_TYPE, "HidP_GetUsageValue returned %#x\n", status );
1987 status = HidP_GetUsageValue( HidP_Feature, HID_USAGE_PAGE_ORDINAL, waveform_list, 3, &value,
1988 preparsed_data, report, caps.FeatureReportByteLength + 1 );
1989 ok( status == HIDP_STATUS_INVALID_REPORT_LENGTH, "HidP_GetUsageValue returned %#x\n", status );
1990 report[0] = 1 - report_id;
1991 status = HidP_GetUsageValue( HidP_Feature, HID_USAGE_PAGE_ORDINAL, waveform_list, 3, &value,
1992 preparsed_data, report, caps.FeatureReportByteLength );
1993 ok( status == (report_id ? HIDP_STATUS_SUCCESS : HIDP_STATUS_INCOMPATIBLE_REPORT_ID),
1994 "HidP_GetUsageValue returned %#x\n", status );
1995 report[0] = 2;
1996 status = HidP_GetUsageValue( HidP_Feature, HID_USAGE_PAGE_ORDINAL, waveform_list, 3, &value,
1997 preparsed_data, report, caps.FeatureReportByteLength );
1998 ok( status == HIDP_STATUS_INCOMPATIBLE_REPORT_ID, "HidP_GetUsageValue returned %#x\n", status );
1999 report[0] = report_id;
2000 status = HidP_GetUsageValue( HidP_Feature, HID_USAGE_PAGE_ORDINAL, 0xdead, 3, &value,
2001 preparsed_data, report, caps.FeatureReportByteLength );
2002 ok( status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetUsageValue returned %#x\n", status );
2004 value = 0xdeadbeef;
2005 status = HidP_GetUsageValue( HidP_Feature, HID_USAGE_PAGE_ORDINAL, waveform_list, 3, &value,
2006 preparsed_data, report, caps.FeatureReportByteLength );
2007 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetUsageValue returned %#x\n", status );
2008 ok( value == HID_USAGE_HAPTICS_WAVEFORM_RUMBLE, "got value %x, expected %#x\n", value,
2009 HID_USAGE_HAPTICS_WAVEFORM_RUMBLE );
2011 memset( buffer, 0xff, sizeof(buffer) );
2012 status = HidP_SetUsageValueArray( HidP_Feature, HID_USAGE_PAGE_HAPTICS, 0,
2013 HID_USAGE_HAPTICS_WAVEFORM_CUTOFF_TIME, buffer, 0,
2014 preparsed_data, report, caps.FeatureReportByteLength );
2015 ok( status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_SetUsageValueArray returned %#x\n", status );
2016 status = HidP_SetUsageValueArray( HidP_Feature, HID_USAGE_PAGE_HAPTICS, 0,
2017 HID_USAGE_HAPTICS_WAVEFORM_CUTOFF_TIME, buffer, 64,
2018 preparsed_data, report, caps.FeatureReportByteLength );
2019 ok( status == HIDP_STATUS_SUCCESS, "HidP_SetUsageValueArray returned %#x\n", status );
2020 ok( !memcmp( report + 9, buffer, 8 ), "unexpected report data\n" );
2022 memset( buffer, 0, sizeof(buffer) );
2023 status = HidP_GetUsageValueArray( HidP_Feature, HID_USAGE_PAGE_HAPTICS, 0,
2024 HID_USAGE_HAPTICS_WAVEFORM_CUTOFF_TIME, buffer, 0,
2025 preparsed_data, report, caps.FeatureReportByteLength );
2026 ok( status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_GetUsageValueArray returned %#x\n", status );
2027 status = HidP_GetUsageValueArray( HidP_Feature, HID_USAGE_PAGE_HAPTICS, 0,
2028 HID_USAGE_HAPTICS_WAVEFORM_CUTOFF_TIME, buffer, 64,
2029 preparsed_data, report, caps.FeatureReportByteLength );
2030 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetUsageValueArray returned %#x\n", status );
2031 memset( buffer + 16, 0xff, 8 );
2032 ok( !memcmp( buffer, buffer + 16, 16 ), "unexpected report value\n" );
2034 value = 0x7fffffff;
2035 status = HidP_SetUsageValue( HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
2036 value, preparsed_data, report, caps.FeatureReportByteLength );
2037 ok( status == HIDP_STATUS_SUCCESS, "HidP_SetUsageValue returned %#x\n", status );
2038 value = 0xdeadbeef;
2039 status = HidP_GetScaledUsageValue( HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
2040 (LONG *)&value, preparsed_data, report, caps.FeatureReportByteLength );
2041 ok( status == HIDP_STATUS_VALUE_OUT_OF_RANGE, "HidP_GetScaledUsageValue returned %#x\n", status );
2042 ok( value == 0, "got value %x, expected %#x\n", value, 0 );
2043 value = 0xdeadbeef;
2044 status = HidP_GetUsageValue( HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
2045 &value, preparsed_data, report, caps.FeatureReportByteLength );
2046 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetUsageValue returned %#x\n", status );
2047 ok( value == 0x7fffffff, "got value %x, expected %#x\n", value, 0x7fffffff );
2049 value = 0x7fff;
2050 status = HidP_SetUsageValue( HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
2051 value, preparsed_data, report, caps.FeatureReportByteLength );
2052 ok( status == HIDP_STATUS_SUCCESS, "HidP_SetUsageValue returned %#x\n", status );
2053 value = 0xdeadbeef;
2054 status = HidP_GetScaledUsageValue( HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
2055 (LONG *)&value, preparsed_data, report, caps.FeatureReportByteLength );
2056 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetScaledUsageValue returned %#x\n", status );
2057 ok( value == 0x0003ffff, "got value %x, expected %#x\n", value, 0x0003ffff );
2059 value = 0;
2060 status = HidP_SetUsageValue( HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
2061 value, preparsed_data, report, caps.FeatureReportByteLength );
2062 ok( status == HIDP_STATUS_SUCCESS, "HidP_SetUsageValue returned %#x\n", status );
2063 value = 0xdeadbeef;
2064 status = HidP_GetScaledUsageValue( HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
2065 (LONG *)&value, preparsed_data, report, caps.FeatureReportByteLength );
2066 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetScaledUsageValue returned %#x\n", status );
2067 ok( value == 0xfff90000, "got value %x, expected %#x\n", value, 0xfff90000 );
2068 status = HidP_SetScaledUsageValue( HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
2069 0x1000, preparsed_data, report, caps.FeatureReportByteLength );
2070 ok( status == HIDP_STATUS_SUCCESS, "HidP_SetScaledUsageValue returned %#x\n", status );
2071 value = 0;
2072 status = HidP_GetUsageValue( HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
2073 &value, preparsed_data, report, caps.FeatureReportByteLength );
2074 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetUsageValue returned %#x\n", status );
2075 ok( value == 0xfffff518, "got value %x, expected %#x\n", value, 0xfffff518 );
2076 status = HidP_SetScaledUsageValue( HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
2077 0, preparsed_data, report, caps.FeatureReportByteLength );
2078 ok( status == HIDP_STATUS_SUCCESS, "HidP_SetScaledUsageValue returned %#x\n", status );
2079 value = 0;
2080 status = HidP_GetUsageValue( HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
2081 &value, preparsed_data, report, caps.FeatureReportByteLength );
2082 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetUsageValue returned %#x\n", status );
2083 ok( value == 0xfffff45e, "got value %x, expected %#x\n", value, 0xfffff45e );
2084 status = HidP_SetScaledUsageValue( HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
2085 0xdead, preparsed_data, report, caps.FeatureReportByteLength );
2086 ok( status == HIDP_STATUS_SUCCESS, "HidP_SetScaledUsageValue returned %#x\n", status );
2087 value = 0;
2088 status = HidP_GetUsageValue( HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
2089 &value, preparsed_data, report, caps.FeatureReportByteLength );
2090 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetUsageValue returned %#x\n", status );
2091 ok( value == 0xfffffe7d, "got value %x, expected %#x\n", value, 0xfffffe7d );
2092 status = HidP_SetScaledUsageValue( HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
2093 0xbeef, preparsed_data, report, caps.FeatureReportByteLength );
2094 ok( status == HIDP_STATUS_SUCCESS, "HidP_SetScaledUsageValue returned %#x\n", status );
2095 value = 0;
2096 status = HidP_GetUsageValue( HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
2097 &value, preparsed_data, report, caps.FeatureReportByteLength );
2098 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetUsageValue returned %#x\n", status );
2099 ok( value == 0xfffffd0b, "got value %x, expected %#x\n", value, 0xfffffd0b );
2101 test_hidp_get_input( file, report_id, caps.InputReportByteLength, preparsed_data );
2102 test_hidp_get_feature( file, report_id, caps.FeatureReportByteLength, preparsed_data );
2103 test_hidp_set_feature( file, report_id, caps.FeatureReportByteLength, preparsed_data );
2104 test_hidp_set_output( file, report_id, caps.OutputReportByteLength, preparsed_data );
2105 test_write_file( file, report_id, caps.OutputReportByteLength );
2107 memset( report, 0xcd, sizeof(report) );
2108 SetLastError( 0xdeadbeef );
2109 ret = ReadFile( file, report, 0, &value, NULL );
2110 ok( !ret && GetLastError() == ERROR_INVALID_USER_BUFFER, "ReadFile failed, last error %u\n",
2111 GetLastError() );
2112 ok( value == 0, "ReadFile returned %x\n", value );
2113 SetLastError( 0xdeadbeef );
2114 ret = ReadFile( file, report, caps.InputReportByteLength - 1, &value, NULL );
2115 ok( !ret && GetLastError() == ERROR_INVALID_USER_BUFFER, "ReadFile failed, last error %u\n",
2116 GetLastError() );
2117 ok( value == 0, "ReadFile returned %x\n", value );
2119 if (polled)
2121 struct hid_expect expect[] =
2124 .code = IOCTL_HID_READ_REPORT,
2125 .report_len = caps.InputReportByteLength - (report_id ? 0 : 1),
2126 .report_buf = {report_id ? report_id : 0x5a,0x5a,0},
2127 .ret_length = 3,
2128 .ret_status = STATUS_SUCCESS,
2131 .code = IOCTL_HID_READ_REPORT,
2132 .report_len = caps.InputReportByteLength - (report_id ? 0 : 1),
2133 .report_buf = {report_id ? report_id : 0x5a,0x5a,1},
2134 .ret_length = 3,
2135 .ret_status = STATUS_SUCCESS,
2139 send_hid_input( file, expect, sizeof(expect) );
2141 memset( report, 0xcd, sizeof(report) );
2142 SetLastError( 0xdeadbeef );
2143 ret = ReadFile( file, report, caps.InputReportByteLength, &value, NULL );
2144 ok( ret, "ReadFile failed, last error %u\n", GetLastError() );
2145 ok( value == (report_id ? 3 : 4), "ReadFile returned %x\n", value );
2146 ok( report[0] == report_id, "unexpected report data\n" );
2148 overlapped.hEvent = CreateEventW( NULL, FALSE, FALSE, NULL );
2149 overlapped2.hEvent = CreateEventW( NULL, FALSE, FALSE, NULL );
2151 /* drain available input reports */
2152 SetLastError( 0xdeadbeef );
2153 while (ReadFile( async_file, report, caps.InputReportByteLength, NULL, &overlapped ))
2154 ResetEvent( overlapped.hEvent );
2155 ok( GetLastError() == ERROR_IO_PENDING, "ReadFile returned error %u\n", GetLastError() );
2156 ret = GetOverlappedResult( async_file, &overlapped, &value, TRUE );
2157 ok( ret, "GetOverlappedResult failed, last error %u\n", GetLastError() );
2158 ok( value == (report_id ? 3 : 4), "GetOverlappedResult returned length %u, expected %u\n",
2159 value, (report_id ? 3 : 4) );
2160 ResetEvent( overlapped.hEvent );
2162 memcpy( buffer, report, caps.InputReportByteLength );
2163 memcpy( buffer + caps.InputReportByteLength, report, caps.InputReportByteLength );
2165 SetLastError( 0xdeadbeef );
2166 ret = ReadFile( async_file, report, caps.InputReportByteLength, NULL, &overlapped );
2167 ok( !ret, "ReadFile succeeded\n" );
2168 ok( GetLastError() == ERROR_IO_PENDING, "ReadFile returned error %u\n", GetLastError() );
2170 SetLastError( 0xdeadbeef );
2171 ret = ReadFile( async_file, buffer, caps.InputReportByteLength, NULL, &overlapped2 );
2172 ok( !ret, "ReadFile succeeded\n" );
2173 ok( GetLastError() == ERROR_IO_PENDING, "ReadFile returned error %u\n", GetLastError() );
2175 /* wait for second report to be ready */
2176 ret = GetOverlappedResult( async_file, &overlapped2, &value, TRUE );
2177 ok( ret, "GetOverlappedResult failed, last error %u\n", GetLastError() );
2178 ok( value == (report_id ? 3 : 4), "GetOverlappedResult returned length %u, expected %u\n",
2179 value, (report_id ? 3 : 4) );
2180 /* first report should be ready and the same */
2181 ret = GetOverlappedResult( async_file, &overlapped, &value, FALSE );
2182 ok( ret, "GetOverlappedResult failed, last error %u\n", GetLastError() );
2183 ok( value == (report_id ? 3 : 4), "GetOverlappedResult returned length %u, expected %u\n",
2184 value, (report_id ? 3 : 4) );
2185 ok( memcmp( report, buffer + caps.InputReportByteLength, caps.InputReportByteLength ),
2186 "expected different report\n" );
2187 ok( !memcmp( report, buffer, caps.InputReportByteLength ), "expected identical reports\n" );
2189 value = 10;
2190 SetLastError( 0xdeadbeef );
2191 ret = sync_ioctl( file, IOCTL_HID_SET_POLL_FREQUENCY_MSEC, &value, sizeof(ULONG), NULL, NULL, INFINITE );
2192 ok( ret, "IOCTL_HID_SET_POLL_FREQUENCY_MSEC failed last error %u\n", GetLastError() );
2194 Sleep( 600 );
2196 SetLastError( 0xdeadbeef );
2197 ret = ReadFile( async_file, report, caps.InputReportByteLength, NULL, &overlapped );
2198 ok( !ret, "ReadFile succeeded\n" );
2199 ok( GetLastError() == ERROR_IO_PENDING, "ReadFile returned error %u\n", GetLastError() );
2201 SetLastError( 0xdeadbeef );
2202 ret = ReadFile( async_file, buffer, caps.InputReportByteLength, NULL, &overlapped2 );
2203 ok( !ret, "ReadFile succeeded\n" );
2204 ok( GetLastError() == ERROR_IO_PENDING, "ReadFile returned error %u\n", GetLastError() );
2206 /* wait for second report to be ready */
2207 ret = GetOverlappedResult( async_file, &overlapped2, &value, TRUE );
2208 ok( ret, "GetOverlappedResult failed, last error %u\n", GetLastError() );
2209 ok( value == (report_id ? 3 : 4), "GetOverlappedResult returned length %u, expected %u\n",
2210 value, (report_id ? 3 : 4) );
2211 /* first report should be ready and the same */
2212 ret = GetOverlappedResult( async_file, &overlapped, &value, FALSE );
2213 ok( ret, "GetOverlappedResult failed, last error %u\n", GetLastError() );
2214 ok( value == (report_id ? 3 : 4), "GetOverlappedResult returned length %u, expected %u\n",
2215 value, (report_id ? 3 : 4) );
2216 ok( !memcmp( report, buffer, caps.InputReportByteLength ), "expected identical reports\n" );
2218 CloseHandle( overlapped.hEvent );
2219 CloseHandle( overlapped2.hEvent );
2221 else
2223 struct hid_expect expect[] =
2226 .code = IOCTL_HID_READ_REPORT,
2227 .report_len = caps.InputReportByteLength - (report_id ? 0 : 1),
2228 .report_buf = {report_id ? report_id : 0x5a,0x5a,0x5a},
2229 .ret_length = 3,
2230 .ret_status = STATUS_SUCCESS,
2233 .code = IOCTL_HID_READ_REPORT,
2234 .report_len = caps.InputReportByteLength - (report_id ? 0 : 1),
2235 .report_buf = {report_id ? report_id : 0xa5,0xa5,0xa5,0xa5,0xa5},
2236 .ret_length = caps.InputReportByteLength - (report_id ? 0 : 1),
2237 .ret_status = STATUS_SUCCESS,
2241 overlapped.hEvent = CreateEventW( NULL, FALSE, FALSE, NULL );
2242 overlapped2.hEvent = CreateEventW( NULL, FALSE, FALSE, NULL );
2244 SetLastError( 0xdeadbeef );
2245 memset( report, 0, sizeof(report) );
2246 ret = ReadFile( async_file, report, caps.InputReportByteLength, NULL, &overlapped );
2247 ok( !ret, "ReadFile succeeded\n" );
2248 ok( GetLastError() == ERROR_IO_PENDING, "ReadFile returned error %u\n", GetLastError() );
2249 Sleep( 50 );
2250 ret = GetOverlappedResult( async_file, &overlapped, &value, FALSE );
2251 ok( !ret, "GetOverlappedResult succeeded\n" );
2252 ok( GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult returned error %u\n", GetLastError() );
2254 SetLastError( 0xdeadbeef );
2255 memset( buffer, 0, sizeof(buffer) );
2256 ret = ReadFile( async_file, buffer, caps.InputReportByteLength, NULL, &overlapped2 );
2257 ok( !ret, "ReadFile succeeded\n" );
2258 ok( GetLastError() == ERROR_IO_PENDING, "ReadFile returned error %u\n", GetLastError() );
2259 Sleep( 50 );
2260 ret = GetOverlappedResult( async_file, &overlapped2, &value, FALSE );
2261 ok( !ret, "GetOverlappedResult succeeded\n" );
2262 ok( GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult returned error %u\n", GetLastError() );
2264 memset( report + caps.InputReportByteLength, 0xa5, 5 );
2265 if (report_id) report[caps.InputReportByteLength] = report_id;
2267 send_hid_input( file, expect, sizeof(expect) );
2269 /* first read should be completed */
2270 ret = GetOverlappedResult( async_file, &overlapped, &value, TRUE );
2271 ok( ret, "GetOverlappedResult failed, last error %u\n", GetLastError() );
2272 ok( value == caps.InputReportByteLength, "got length %u, expected %u\n", value, caps.InputReportByteLength );
2273 /* second read should still be pending */
2274 Sleep( 50 );
2275 ret = GetOverlappedResult( async_file, &overlapped2, &value, FALSE );
2276 ok( !ret, "GetOverlappedResult succeeded\n" );
2277 ok( GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult returned error %u\n", GetLastError() );
2279 memset( buffer + caps.InputReportByteLength, 0x3b, 5 );
2280 if (report_id) buffer[caps.InputReportByteLength] = report_id;
2281 memset( expect[1].report_buf, 0x3b, 5 );
2282 if (report_id) expect[1].report_buf[0] = report_id;
2284 send_hid_input( file, expect, sizeof(expect) );
2286 ret = GetOverlappedResult( async_file, &overlapped2, &value, TRUE );
2287 ok( ret, "GetOverlappedResult failed, last error %u\n", GetLastError() );
2288 ok( value == caps.InputReportByteLength, "got length %u, expected %u\n", value, caps.InputReportByteLength );
2290 off = report_id ? 0 : 1;
2291 ok( memcmp( report, buffer, caps.InputReportByteLength ), "expected different report\n" );
2292 ok( !memcmp( report + off, report + caps.InputReportByteLength, caps.InputReportByteLength - off ),
2293 "expected identical reports\n" );
2294 ok( !memcmp( buffer + off, buffer + caps.InputReportByteLength, caps.InputReportByteLength - off ),
2295 "expected identical reports\n" );
2297 CloseHandle( overlapped.hEvent );
2298 CloseHandle( overlapped2.hEvent );
2301 HidD_FreePreparsedData( preparsed_data );
2304 static void test_hid_device( DWORD report_id, DWORD polled, const HIDP_CAPS *expect_caps )
2306 char buffer[FIELD_OFFSET( SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath[MAX_PATH] )];
2307 SP_DEVICE_INTERFACE_DATA iface = {sizeof(SP_DEVICE_INTERFACE_DATA)};
2308 SP_DEVICE_INTERFACE_DETAIL_DATA_W *iface_detail = (void *)buffer;
2309 SP_DEVINFO_DATA device = {sizeof(SP_DEVINFO_DATA)};
2310 ULONG count, poll_freq, out_len;
2311 HANDLE file, async_file;
2312 BOOL ret, found = FALSE;
2313 OBJECT_ATTRIBUTES attr;
2314 UNICODE_STRING string;
2315 IO_STATUS_BLOCK io;
2316 NTSTATUS status;
2317 unsigned int i;
2318 HDEVINFO set;
2320 winetest_push_context( "id %d%s", report_id, polled ? " poll" : "" );
2322 set = SetupDiGetClassDevsW( &GUID_DEVINTERFACE_HID, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT );
2323 ok( set != INVALID_HANDLE_VALUE, "failed to get device list, error %#x\n", GetLastError() );
2325 for (i = 0; SetupDiEnumDeviceInfo( set, i, &device ); ++i)
2327 ret = SetupDiEnumDeviceInterfaces( set, &device, &GUID_DEVINTERFACE_HID, 0, &iface );
2328 ok( ret, "failed to get interface, error %#x\n", GetLastError() );
2329 ok( IsEqualGUID( &iface.InterfaceClassGuid, &GUID_DEVINTERFACE_HID ), "wrong class %s\n",
2330 debugstr_guid( &iface.InterfaceClassGuid ) );
2331 ok( iface.Flags == SPINT_ACTIVE, "got flags %#x\n", iface.Flags );
2333 iface_detail->cbSize = sizeof(*iface_detail);
2334 ret = SetupDiGetDeviceInterfaceDetailW( set, &iface, iface_detail, sizeof(buffer), NULL, NULL );
2335 ok( ret, "failed to get interface path, error %#x\n", GetLastError() );
2337 if (wcsstr( iface_detail->DevicePath, L"\\\\?\\hid#winetest#1" ))
2339 found = TRUE;
2340 break;
2344 SetupDiDestroyDeviceInfoList( set );
2346 todo_wine
2347 ok( found, "didn't find device\n" );
2349 file = CreateFileW( iface_detail->DevicePath, FILE_READ_ACCESS | FILE_WRITE_ACCESS,
2350 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
2351 ok( file != INVALID_HANDLE_VALUE, "got error %u\n", GetLastError() );
2353 count = 0xdeadbeef;
2354 SetLastError( 0xdeadbeef );
2355 ret = HidD_GetNumInputBuffers( file, &count );
2356 ok( ret, "HidD_GetNumInputBuffers failed last error %u\n", GetLastError() );
2357 ok( count == 32, "HidD_GetNumInputBuffers returned %u\n", count );
2359 SetLastError( 0xdeadbeef );
2360 ret = HidD_SetNumInputBuffers( file, 1 );
2361 ok( !ret, "HidD_SetNumInputBuffers succeeded\n" );
2362 ok( GetLastError() == ERROR_INVALID_PARAMETER, "HidD_SetNumInputBuffers returned error %u\n",
2363 GetLastError() );
2364 SetLastError( 0xdeadbeef );
2365 ret = HidD_SetNumInputBuffers( file, 513 );
2366 ok( !ret, "HidD_SetNumInputBuffers succeeded\n" );
2367 ok( GetLastError() == ERROR_INVALID_PARAMETER, "HidD_SetNumInputBuffers returned error %u\n",
2368 GetLastError() );
2370 SetLastError( 0xdeadbeef );
2371 ret = HidD_SetNumInputBuffers( file, 16 );
2372 ok( ret, "HidD_SetNumInputBuffers failed last error %u\n", GetLastError() );
2374 count = 0xdeadbeef;
2375 SetLastError( 0xdeadbeef );
2376 ret = HidD_GetNumInputBuffers( file, &count );
2377 ok( ret, "HidD_GetNumInputBuffers failed last error %u\n", GetLastError() );
2378 ok( count == 16, "HidD_GetNumInputBuffers returned %u\n", count );
2380 async_file = CreateFileW( iface_detail->DevicePath, FILE_READ_ACCESS | FILE_WRITE_ACCESS,
2381 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
2382 FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING, NULL );
2383 ok( async_file != INVALID_HANDLE_VALUE, "got error %u\n", GetLastError() );
2385 count = 0xdeadbeef;
2386 SetLastError( 0xdeadbeef );
2387 ret = HidD_GetNumInputBuffers( async_file, &count );
2388 ok( ret, "HidD_GetNumInputBuffers failed last error %u\n", GetLastError() );
2389 ok( count == 32, "HidD_GetNumInputBuffers returned %u\n", count );
2391 SetLastError( 0xdeadbeef );
2392 ret = HidD_SetNumInputBuffers( async_file, 2 );
2393 ok( ret, "HidD_SetNumInputBuffers failed last error %u\n", GetLastError() );
2395 count = 0xdeadbeef;
2396 SetLastError( 0xdeadbeef );
2397 ret = HidD_GetNumInputBuffers( async_file, &count );
2398 ok( ret, "HidD_GetNumInputBuffers failed last error %u\n", GetLastError() );
2399 ok( count == 2, "HidD_GetNumInputBuffers returned %u\n", count );
2400 count = 0xdeadbeef;
2401 SetLastError( 0xdeadbeef );
2402 ret = HidD_GetNumInputBuffers( file, &count );
2403 ok( ret, "HidD_GetNumInputBuffers failed last error %u\n", GetLastError() );
2404 ok( count == 16, "HidD_GetNumInputBuffers returned %u\n", count );
2406 if (polled)
2408 out_len = sizeof(ULONG);
2409 SetLastError( 0xdeadbeef );
2410 ret = sync_ioctl( file, IOCTL_HID_GET_POLL_FREQUENCY_MSEC, NULL, 0, &poll_freq, &out_len, INFINITE );
2411 ok( ret, "IOCTL_HID_GET_POLL_FREQUENCY_MSEC failed last error %u\n", GetLastError() );
2412 ok( out_len == sizeof(ULONG), "got out_len %u, expected sizeof(ULONG)\n", out_len );
2413 todo_wine
2414 ok( poll_freq == 5, "got poll_freq %u, expected 5\n", poll_freq );
2416 out_len = 0;
2417 poll_freq = 500;
2418 SetLastError( 0xdeadbeef );
2419 ret = sync_ioctl( file, IOCTL_HID_SET_POLL_FREQUENCY_MSEC, &poll_freq, sizeof(ULONG), NULL, &out_len, INFINITE );
2420 ok( ret, "IOCTL_HID_SET_POLL_FREQUENCY_MSEC failed last error %u\n", GetLastError() );
2421 ok( out_len == 0, "got out_len %u, expected 0\n", out_len );
2423 out_len = 0;
2424 poll_freq = 10001;
2425 SetLastError( 0xdeadbeef );
2426 ret = sync_ioctl( file, IOCTL_HID_SET_POLL_FREQUENCY_MSEC, &poll_freq, sizeof(ULONG), NULL, &out_len, INFINITE );
2427 ok( ret, "IOCTL_HID_SET_POLL_FREQUENCY_MSEC failed last error %u\n", GetLastError() );
2428 ok( out_len == 0, "got out_len %u, expected 0\n", out_len );
2430 out_len = 0;
2431 poll_freq = 0;
2432 SetLastError( 0xdeadbeef );
2433 ret = sync_ioctl( file, IOCTL_HID_SET_POLL_FREQUENCY_MSEC, &poll_freq, sizeof(ULONG), NULL, &out_len, INFINITE );
2434 ok( ret, "IOCTL_HID_SET_POLL_FREQUENCY_MSEC failed last error %u\n", GetLastError() );
2435 ok( out_len == 0, "got out_len %u, expected 0\n", out_len );
2437 out_len = sizeof(ULONG);
2438 SetLastError( 0xdeadbeef );
2439 ret = sync_ioctl( file, IOCTL_HID_GET_POLL_FREQUENCY_MSEC, NULL, 0, &poll_freq, &out_len, INFINITE );
2440 ok( ret, "IOCTL_HID_GET_POLL_FREQUENCY_MSEC failed last error %u\n", GetLastError() );
2441 ok( out_len == sizeof(ULONG), "got out_len %u, expected sizeof(ULONG)\n", out_len );
2442 ok( poll_freq == 10000, "got poll_freq %u, expected 10000\n", poll_freq );
2444 out_len = 0;
2445 poll_freq = 500;
2446 SetLastError( 0xdeadbeef );
2447 ret = sync_ioctl( file, IOCTL_HID_SET_POLL_FREQUENCY_MSEC, &poll_freq, sizeof(ULONG), NULL, &out_len, INFINITE );
2448 ok( ret, "IOCTL_HID_SET_POLL_FREQUENCY_MSEC failed last error %u\n", GetLastError() );
2449 ok( out_len == 0, "got out_len %u, expected 0\n", out_len );
2451 out_len = sizeof(ULONG);
2452 SetLastError( 0xdeadbeef );
2453 ret = sync_ioctl( async_file, IOCTL_HID_GET_POLL_FREQUENCY_MSEC, NULL, 0, &poll_freq, &out_len, INFINITE );
2454 ok( ret, "IOCTL_HID_GET_POLL_FREQUENCY_MSEC failed last error %u\n", GetLastError() );
2455 ok( out_len == sizeof(ULONG), "got out_len %u, expected sizeof(ULONG)\n", out_len );
2456 ok( poll_freq == 500, "got poll_freq %u, expected 500\n", poll_freq );
2459 test_hidp( file, async_file, report_id, polled, expect_caps );
2461 CloseHandle( async_file );
2462 CloseHandle( file );
2464 RtlInitUnicodeString( &string, L"\\??\\root#winetest#0#{deadbeef-29ef-4538-a5fd-b69573a362c0}" );
2465 InitializeObjectAttributes( &attr, &string, OBJ_CASE_INSENSITIVE, NULL, NULL );
2466 status = NtOpenFile( &file, SYNCHRONIZE, &attr, &io, 0, FILE_SYNCHRONOUS_IO_NONALERT );
2467 todo_wine
2468 ok( status == STATUS_UNSUCCESSFUL, "got %#x\n", status );
2470 winetest_pop_context();
2473 static void test_hid_driver( DWORD report_id, DWORD polled )
2475 #include "psh_hid_macros.h"
2476 /* Replace REPORT_ID with USAGE_PAGE when id is 0 */
2477 #define REPORT_ID_OR_USAGE_PAGE(size, id, off) SHORT_ITEM_1((id ? 8 : 0), 1, (id + off))
2478 const unsigned char report_desc[] =
2480 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
2481 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
2482 COLLECTION(1, Application),
2483 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
2484 COLLECTION(1, Logical),
2485 REPORT_ID_OR_USAGE_PAGE(1, report_id, 0),
2486 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
2487 USAGE(1, HID_USAGE_GENERIC_X),
2488 USAGE(1, HID_USAGE_GENERIC_Y),
2489 LOGICAL_MINIMUM(1, -128),
2490 LOGICAL_MAXIMUM(1, 127),
2491 REPORT_SIZE(1, 8),
2492 REPORT_COUNT(1, 2),
2493 INPUT(1, Data|Var|Abs),
2495 USAGE_PAGE(1, HID_USAGE_PAGE_BUTTON),
2496 USAGE_MINIMUM(1, 1),
2497 USAGE_MAXIMUM(1, 8),
2498 LOGICAL_MINIMUM(1, 0),
2499 LOGICAL_MAXIMUM(1, 1),
2500 REPORT_COUNT(1, 8),
2501 REPORT_SIZE(1, 1),
2502 INPUT(1, Data|Var|Abs),
2504 USAGE_MINIMUM(1, 0x18),
2505 USAGE_MAXIMUM(1, 0x1f),
2506 LOGICAL_MINIMUM(1, 0),
2507 LOGICAL_MAXIMUM(1, 1),
2508 REPORT_COUNT(1, 8),
2509 REPORT_SIZE(1, 1),
2510 INPUT(1, Cnst|Var|Abs),
2511 REPORT_SIZE(1, 8),
2512 INPUT(1, Cnst|Var|Abs),
2513 /* needs to be 8 bit aligned as next has Buff */
2515 USAGE_MINIMUM(4, (HID_USAGE_PAGE_KEYBOARD<<16)|0x8),
2516 USAGE_MAXIMUM(4, (HID_USAGE_PAGE_KEYBOARD<<16)|0xf),
2517 LOGICAL_MINIMUM(1, 0),
2518 LOGICAL_MAXIMUM(1, 8),
2519 REPORT_COUNT(1, 2),
2520 REPORT_SIZE(1, 8),
2521 INPUT(2, Data|Ary|Rel|Wrap|Lin|Pref|Null|Vol|Buff),
2523 /* needs to be 8 bit aligned as previous has Buff */
2524 USAGE(1, 0x20),
2525 LOGICAL_MINIMUM(1, 0),
2526 LOGICAL_MAXIMUM(1, 1),
2527 REPORT_COUNT(1, 8),
2528 REPORT_SIZE(1, 1),
2529 INPUT(1, Data|Var|Abs),
2530 USAGE_MINIMUM(1, 0x21),
2531 USAGE_MAXIMUM(1, 0x22),
2532 REPORT_COUNT(1, 2),
2533 REPORT_SIZE(1, 0),
2534 INPUT(1, Data|Var|Abs),
2535 USAGE(1, 0x23),
2536 REPORT_COUNT(1, 0),
2537 REPORT_SIZE(1, 1),
2538 INPUT(1, Data|Var|Abs),
2540 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
2541 USAGE(1, HID_USAGE_GENERIC_HATSWITCH),
2542 LOGICAL_MINIMUM(1, 1),
2543 LOGICAL_MAXIMUM(1, 8),
2544 REPORT_SIZE(1, 4),
2545 REPORT_COUNT(1, 2),
2546 INPUT(1, Data|Var|Abs),
2548 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
2549 USAGE(1, HID_USAGE_GENERIC_Z),
2550 LOGICAL_MINIMUM(4, 0x00000000),
2551 LOGICAL_MAXIMUM(4, 0x3fffffff),
2552 PHYSICAL_MINIMUM(4, 0x80000000),
2553 PHYSICAL_MAXIMUM(4, 0x7fffffff),
2554 REPORT_SIZE(1, 32),
2555 REPORT_COUNT(1, 1),
2556 INPUT(1, Data|Var|Abs),
2558 /* reset physical range to its default interpretation */
2559 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
2560 USAGE(1, HID_USAGE_GENERIC_RX),
2561 PHYSICAL_MINIMUM(4, 0),
2562 PHYSICAL_MAXIMUM(4, 0),
2563 REPORT_SIZE(1, 32),
2564 REPORT_COUNT(1, 1),
2565 INPUT(1, Data|Var|Abs),
2567 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
2568 USAGE(1, HID_USAGE_GENERIC_RY),
2569 LOGICAL_MINIMUM(4, 0x7fff),
2570 LOGICAL_MAXIMUM(4, 0x0000),
2571 PHYSICAL_MINIMUM(4, 0x0000),
2572 PHYSICAL_MAXIMUM(4, 0x7fff),
2573 REPORT_SIZE(1, 32),
2574 REPORT_COUNT(1, 1),
2575 INPUT(1, Data|Var|Abs),
2576 END_COLLECTION,
2578 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
2579 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
2580 COLLECTION(1, Report),
2581 REPORT_ID_OR_USAGE_PAGE(1, report_id, 1),
2582 USAGE_PAGE(1, HID_USAGE_PAGE_BUTTON),
2583 USAGE_MINIMUM(1, 9),
2584 USAGE_MAXIMUM(1, 10),
2585 LOGICAL_MINIMUM(1, 0),
2586 LOGICAL_MAXIMUM(1, 1),
2587 REPORT_COUNT(1, 8),
2588 REPORT_SIZE(1, 1),
2589 INPUT(1, Data|Var|Abs),
2590 END_COLLECTION,
2592 USAGE_PAGE(1, HID_USAGE_PAGE_LED),
2593 USAGE(1, HID_USAGE_LED_GREEN),
2594 COLLECTION(1, Report),
2595 REPORT_ID_OR_USAGE_PAGE(1, report_id, 0),
2596 USAGE_PAGE(1, HID_USAGE_PAGE_LED),
2597 USAGE(1, 1),
2598 USAGE(1, 2),
2599 USAGE(1, 3),
2600 USAGE(1, 4),
2601 USAGE(1, 5),
2602 USAGE(1, 6),
2603 USAGE(1, 7),
2604 USAGE(1, 8),
2605 LOGICAL_MINIMUM(1, 0),
2606 LOGICAL_MAXIMUM(1, 1),
2607 PHYSICAL_MINIMUM(1, 0),
2608 PHYSICAL_MAXIMUM(1, 1),
2609 REPORT_COUNT(1, 8),
2610 REPORT_SIZE(1, 1),
2611 INPUT(1, Data|Var|Abs),
2613 USAGE(4, (HID_USAGE_PAGE_KEYBOARD<<16)|0x8c),
2614 USAGE(4, (HID_USAGE_PAGE_KEYBOARD<<16)|0x8d),
2615 USAGE(4, (HID_USAGE_PAGE_KEYBOARD<<16)|0x8e),
2616 USAGE(4, (HID_USAGE_PAGE_KEYBOARD<<16)|0x8f),
2617 LOGICAL_MINIMUM(1, 1),
2618 LOGICAL_MAXIMUM(1, 16),
2619 REPORT_COUNT(1, 2),
2620 REPORT_SIZE(1, 8),
2621 INPUT(1, Data|Ary|Abs),
2622 END_COLLECTION,
2624 USAGE_PAGE(2, HID_USAGE_PAGE_HAPTICS),
2625 USAGE(1, HID_USAGE_HAPTICS_SIMPLE_CONTROLLER),
2626 COLLECTION(1, Logical),
2627 REPORT_ID_OR_USAGE_PAGE(1, report_id, 0),
2628 USAGE_PAGE(2, HID_USAGE_PAGE_HAPTICS),
2630 USAGE(1, HID_USAGE_HAPTICS_WAVEFORM_LIST),
2631 COLLECTION(1, NamedArray),
2632 USAGE_PAGE(1, HID_USAGE_PAGE_ORDINAL),
2633 USAGE(1, 3), /* HID_USAGE_HAPTICS_WAVEFORM_RUMBLE */
2634 USAGE(1, 4), /* HID_USAGE_HAPTICS_WAVEFORM_BUZZ */
2635 LOGICAL_MINIMUM(2, 0x0000),
2636 LOGICAL_MAXIMUM(2, 0xffff),
2637 REPORT_COUNT(1, 2),
2638 REPORT_SIZE(1, 16),
2639 FEATURE(1, Data|Var|Abs|Null),
2640 END_COLLECTION,
2642 USAGE_PAGE(2, HID_USAGE_PAGE_HAPTICS),
2643 USAGE(1, HID_USAGE_HAPTICS_DURATION_LIST),
2644 COLLECTION(1, NamedArray),
2645 USAGE_PAGE(1, HID_USAGE_PAGE_ORDINAL),
2646 USAGE(1, 3), /* 0 (HID_USAGE_HAPTICS_WAVEFORM_RUMBLE) */
2647 USAGE(1, 4), /* 0 (HID_USAGE_HAPTICS_WAVEFORM_BUZZ) */
2648 LOGICAL_MINIMUM(2, 0x0000),
2649 LOGICAL_MAXIMUM(2, 0xffff),
2650 REPORT_COUNT(1, 2),
2651 REPORT_SIZE(1, 16),
2652 FEATURE(1, Data|Var|Abs|Null),
2653 END_COLLECTION,
2655 USAGE_PAGE(2, HID_USAGE_PAGE_HAPTICS),
2656 USAGE(1, HID_USAGE_HAPTICS_WAVEFORM_CUTOFF_TIME),
2657 UNIT(2, 0x1001), /* seconds */
2658 UNIT_EXPONENT(1, -3), /* 10^-3 */
2659 LOGICAL_MINIMUM(2, 0x8000),
2660 LOGICAL_MAXIMUM(2, 0x7fff),
2661 PHYSICAL_MINIMUM(4, 0x00000000),
2662 PHYSICAL_MAXIMUM(4, 0xffffffff),
2663 REPORT_SIZE(1, 32),
2664 REPORT_COUNT(1, 2),
2665 FEATURE(1, Data|Var|Abs),
2666 /* reset global items */
2667 UNIT(1, 0), /* None */
2668 UNIT_EXPONENT(1, 0),
2670 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
2671 USAGE(1, HID_USAGE_GENERIC_Z),
2672 LOGICAL_MINIMUM(4, 0x0000),
2673 LOGICAL_MAXIMUM(4, 0x7fff),
2674 PHYSICAL_MINIMUM(4, 0xfff90000),
2675 PHYSICAL_MAXIMUM(4, 0x0003ffff),
2676 REPORT_SIZE(1, 32),
2677 REPORT_COUNT(1, 1),
2678 FEATURE(1, Data|Var|Abs),
2679 END_COLLECTION,
2681 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
2682 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
2683 COLLECTION(1, Report),
2684 REPORT_ID_OR_USAGE_PAGE(1, report_id, 1),
2685 USAGE_PAGE(1, HID_USAGE_PAGE_BUTTON),
2686 USAGE_MINIMUM(1, 9),
2687 USAGE_MAXIMUM(1, 10),
2688 LOGICAL_MINIMUM(1, 0),
2689 LOGICAL_MAXIMUM(1, 1),
2690 PHYSICAL_MINIMUM(1, 0),
2691 PHYSICAL_MAXIMUM(1, 1),
2692 REPORT_COUNT(1, 8),
2693 REPORT_SIZE(1, 1),
2694 FEATURE(1, Data|Var|Abs),
2695 END_COLLECTION,
2697 USAGE_PAGE(1, HID_USAGE_PAGE_LED),
2698 USAGE(1, HID_USAGE_LED_GREEN),
2699 COLLECTION(1, Report),
2700 REPORT_ID_OR_USAGE_PAGE(1, report_id, 0),
2701 USAGE_PAGE(1, HID_USAGE_PAGE_LED),
2702 REPORT_COUNT(1, 8),
2703 REPORT_SIZE(1, 1),
2704 OUTPUT(1, Cnst|Var|Abs),
2705 END_COLLECTION,
2707 USAGE_PAGE(1, HID_USAGE_PAGE_LED),
2708 USAGE(1, HID_USAGE_LED_RED),
2709 COLLECTION(1, Report),
2710 REPORT_ID_OR_USAGE_PAGE(1, report_id, 1),
2711 USAGE_PAGE(1, HID_USAGE_PAGE_LED),
2712 REPORT_COUNT(1, 8),
2713 REPORT_SIZE(1, 1),
2714 OUTPUT(1, Cnst|Var|Abs),
2715 END_COLLECTION,
2716 END_COLLECTION,
2718 #undef REPORT_ID_OR_USAGE_PAGE
2719 #include "pop_hid_macros.h"
2721 static const HID_DEVICE_ATTRIBUTES attributes =
2723 .Size = sizeof(HID_DEVICE_ATTRIBUTES),
2724 .VendorID = 0x1209,
2725 .ProductID = 0x0001,
2726 .VersionNumber = 0x0100,
2728 const HIDP_CAPS caps =
2730 .Usage = HID_USAGE_GENERIC_JOYSTICK,
2731 .UsagePage = HID_USAGE_PAGE_GENERIC,
2732 .InputReportByteLength = report_id ? 32 : 33,
2733 .OutputReportByteLength = report_id ? 2 : 3,
2734 .FeatureReportByteLength = report_id ? 21 : 22,
2735 .NumberLinkCollectionNodes = 10,
2736 .NumberInputButtonCaps = 17,
2737 .NumberInputValueCaps = 7,
2738 .NumberInputDataIndices = 47,
2739 .NumberFeatureButtonCaps = 1,
2740 .NumberFeatureValueCaps = 6,
2741 .NumberFeatureDataIndices = 8,
2743 const struct hid_expect expect_in =
2745 .code = IOCTL_HID_READ_REPORT,
2746 .report_len = caps.InputReportByteLength - (report_id ? 0 : 1),
2747 .report_buf = {report_id ? report_id : 0x5a,0x5a,0x5a},
2748 .ret_length = 3,
2749 .ret_status = STATUS_SUCCESS,
2752 WCHAR cwd[MAX_PATH], tempdir[MAX_PATH];
2753 LSTATUS status;
2754 HKEY hkey;
2756 GetCurrentDirectoryW( ARRAY_SIZE(cwd), cwd );
2757 GetTempPathW( ARRAY_SIZE(tempdir), tempdir );
2758 SetCurrentDirectoryW( tempdir );
2760 status = RegCreateKeyExW( HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Services\\winetest",
2761 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL );
2762 ok( !status, "RegCreateKeyExW returned %#x\n", status );
2764 status = RegSetValueExW( hkey, L"ReportID", 0, REG_DWORD, (void *)&report_id, sizeof(report_id) );
2765 ok( !status, "RegSetValueExW returned %#x\n", status );
2767 status = RegSetValueExW( hkey, L"PolledMode", 0, REG_DWORD, (void *)&polled, sizeof(polled) );
2768 ok( !status, "RegSetValueExW returned %#x\n", status );
2770 status = RegSetValueExW( hkey, L"Descriptor", 0, REG_BINARY, (void *)report_desc, sizeof(report_desc) );
2771 ok( !status, "RegSetValueExW returned %#x\n", status );
2773 status = RegSetValueExW( hkey, L"Attributes", 0, REG_BINARY, (void *)&attributes, sizeof(attributes) );
2774 ok( !status, "RegSetValueExW returned %#x\n", status );
2776 status = RegSetValueExW( hkey, L"Caps", 0, REG_BINARY, (void *)&caps, sizeof(caps) );
2777 ok( !status, "RegSetValueExW returned %#x\n", status );
2779 status = RegSetValueExW( hkey, L"Expect", 0, REG_BINARY, NULL, 0 );
2780 ok( !status, "RegSetValueExW returned %#x\n", status );
2782 status = RegSetValueExW( hkey, L"Input", 0, REG_BINARY, (void *)&expect_in, polled ? sizeof(expect_in) : 0 );
2783 ok( !status, "RegSetValueExW returned %#x\n", status );
2785 if (pnp_driver_start( L"driver_hid.dll" )) test_hid_device( report_id, polled, &caps );
2787 pnp_driver_stop();
2788 SetCurrentDirectoryW( cwd );
2791 /* undocumented HID internal preparsed data structure */
2793 struct hidp_kdr_caps
2795 USHORT usage_page;
2796 UCHAR report_id;
2797 UCHAR start_bit;
2798 USHORT bit_size;
2799 USHORT report_count;
2800 USHORT start_byte;
2801 USHORT total_bits;
2802 ULONG bit_field;
2803 USHORT end_byte;
2804 USHORT link_collection;
2805 USAGE link_usage_page;
2806 USAGE link_usage;
2807 ULONG flags;
2808 ULONG padding[8];
2809 USAGE usage_min;
2810 USAGE usage_max;
2811 USHORT string_min;
2812 USHORT string_max;
2813 USHORT designator_min;
2814 USHORT designator_max;
2815 USHORT data_index_min;
2816 USHORT data_index_max;
2817 USHORT null_value;
2818 USHORT unknown;
2819 LONG logical_min;
2820 LONG logical_max;
2821 LONG physical_min;
2822 LONG physical_max;
2823 LONG units;
2824 LONG units_exp;
2827 /* named array continues on next caps */
2828 #define HIDP_KDR_CAPS_ARRAY_HAS_MORE 0x01
2829 #define HIDP_KDR_CAPS_IS_CONSTANT 0x02
2830 #define HIDP_KDR_CAPS_IS_BUTTON 0x04
2831 #define HIDP_KDR_CAPS_IS_ABSOLUTE 0x08
2832 #define HIDP_KDR_CAPS_IS_RANGE 0x10
2833 #define HIDP_KDR_CAPS_IS_STRING_RANGE 0x40
2834 #define HIDP_KDR_CAPS_IS_DESIGNATOR_RANGE 0x80
2836 struct hidp_kdr_node
2838 USAGE usage;
2839 USAGE usage_page;
2840 USHORT parent;
2841 USHORT number_of_children;
2842 USHORT next_sibling;
2843 USHORT first_child;
2844 ULONG collection_type;
2847 struct hidp_kdr
2849 char magic[8];
2850 USAGE usage;
2851 USAGE usage_page;
2852 USHORT unknown[2];
2853 USHORT input_caps_start;
2854 USHORT input_caps_count;
2855 USHORT input_caps_end;
2856 USHORT input_report_byte_length;
2857 USHORT output_caps_start;
2858 USHORT output_caps_count;
2859 USHORT output_caps_end;
2860 USHORT output_report_byte_length;
2861 USHORT feature_caps_start;
2862 USHORT feature_caps_count;
2863 USHORT feature_caps_end;
2864 USHORT feature_report_byte_length;
2865 USHORT caps_size;
2866 USHORT number_link_collection_nodes;
2867 struct hidp_kdr_caps caps[1];
2868 /* struct hidp_kdr_node nodes[1] */
2871 static void test_hidp_kdr(void)
2873 #include "psh_hid_macros.h"
2874 const unsigned char report_desc[] =
2876 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
2877 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
2878 COLLECTION(1, Application),
2879 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
2880 LOGICAL_MINIMUM(1, 1),
2881 LOGICAL_MAXIMUM(1, 127),
2882 PHYSICAL_MINIMUM(1, -128),
2883 PHYSICAL_MAXIMUM(1, 127),
2885 USAGE(1, HID_USAGE_GENERIC_RZ),
2886 REPORT_SIZE(1, 16),
2887 REPORT_COUNT(1, 0),
2888 FEATURE(1, Data|Var|Abs),
2889 USAGE(1, HID_USAGE_GENERIC_SLIDER),
2890 REPORT_SIZE(1, 16),
2891 REPORT_COUNT(1, 1),
2892 FEATURE(1, Data|Var|Abs),
2894 USAGE(1, HID_USAGE_GENERIC_X),
2895 REPORT_SIZE(1, 8),
2896 REPORT_COUNT(1, 1),
2897 UNIT(1, 0x100e),
2898 UNIT_EXPONENT(1, -3),
2899 INPUT(1, Data|Var|Abs),
2900 UNIT_EXPONENT(1, 0),
2901 UNIT(1, 0),
2902 USAGE(1, HID_USAGE_GENERIC_Y),
2903 DESIGNATOR_MINIMUM(1, 1),
2904 DESIGNATOR_MAXIMUM(1, 4),
2905 REPORT_SIZE(1, 8),
2906 REPORT_COUNT(1, 1),
2907 INPUT(1, Cnst|Var|Abs),
2908 USAGE(1, HID_USAGE_GENERIC_Z),
2909 REPORT_SIZE(1, 8),
2910 REPORT_COUNT(1, 1),
2911 INPUT(1, Data|Var|Rel),
2912 USAGE(1, HID_USAGE_GENERIC_RX),
2913 USAGE(1, HID_USAGE_GENERIC_RY),
2914 REPORT_SIZE(1, 16),
2915 REPORT_COUNT(1, 2),
2916 LOGICAL_MINIMUM(1, 7),
2917 INPUT(1, Data|Var|Abs|Null),
2919 COLLECTION(1, Application),
2920 USAGE(4, (HID_USAGE_PAGE_BUTTON << 16)|1),
2921 USAGE(4, (HID_USAGE_PAGE_BUTTON << 16)|2),
2922 REPORT_SIZE(1, 1),
2923 REPORT_COUNT(1, 8),
2924 LOGICAL_MINIMUM(1, 0),
2925 LOGICAL_MAXIMUM(1, 1),
2926 INPUT(1, Data|Var|Abs),
2928 USAGE_MINIMUM(4, (HID_USAGE_PAGE_BUTTON << 16)|3),
2929 USAGE_MAXIMUM(4, (HID_USAGE_PAGE_BUTTON << 16)|8),
2930 REPORT_SIZE(1, 8),
2931 REPORT_COUNT(1, 1),
2932 LOGICAL_MINIMUM(1, 3),
2933 LOGICAL_MAXIMUM(1, 8),
2934 INPUT(1, Data|Ary|Abs),
2936 USAGE_MINIMUM(4, (HID_USAGE_PAGE_BUTTON << 16)|9),
2937 USAGE_MAXIMUM(4, (HID_USAGE_PAGE_BUTTON << 16)|12),
2938 REPORT_SIZE(1, 8),
2939 REPORT_COUNT(1, 4),
2940 LOGICAL_MINIMUM(1, 9),
2941 LOGICAL_MAXIMUM(1, 12),
2942 INPUT(2, Data|Ary|Abs|Buff),
2944 USAGE(4, (HID_USAGE_PAGE_BUTTON << 16)|13),
2945 USAGE(4, (HID_USAGE_PAGE_BUTTON << 16)|14),
2946 USAGE(4, (HID_USAGE_PAGE_BUTTON << 16)|15),
2947 USAGE(4, (HID_USAGE_PAGE_BUTTON << 16)|16),
2948 REPORT_SIZE(1, 8),
2949 REPORT_COUNT(1, 1),
2950 LOGICAL_MINIMUM(1, 13),
2951 LOGICAL_MAXIMUM(1, 16),
2952 INPUT(1, Data|Ary|Abs),
2953 END_COLLECTION,
2954 END_COLLECTION,
2956 #include "pop_hid_macros.h"
2958 static const HIDP_CAPS expect_hidp_caps =
2960 .Usage = HID_USAGE_GENERIC_JOYSTICK,
2961 .UsagePage = HID_USAGE_PAGE_GENERIC,
2962 .InputReportByteLength = 15,
2964 static const HID_DEVICE_ATTRIBUTES attributes =
2966 .Size = sizeof(HID_DEVICE_ATTRIBUTES),
2967 .VendorID = 0x1209,
2968 .ProductID = 0x0001,
2969 .VersionNumber = 0x0100,
2971 static const struct hidp_kdr expect_kdr =
2973 .magic = "HidP KDR",
2974 .usage = 0x04,
2975 .usage_page = 0x01,
2976 .input_caps_count = 13,
2977 .input_caps_end = 13,
2978 .input_report_byte_length = 15,
2979 .output_caps_start = 13,
2980 .output_caps_end = 13,
2981 .feature_caps_start = 13,
2982 .feature_caps_count = 2,
2983 .feature_caps_end = 14,
2984 .feature_report_byte_length = 3,
2985 .caps_size = 1560,
2986 .number_link_collection_nodes = 2,
2988 static const struct hidp_kdr_caps expect_caps[] =
2991 .usage_page = 0x01, .bit_size = 0x08, .report_count = 0x1, .start_byte = 0x1, .total_bits = 0x08,
2992 .bit_field = 0x002, .end_byte = 0x2, .link_usage_page = 0x01, .link_usage = 0x04, .flags = 0x08,
2993 .usage_min = 0x30, .usage_max = 0x30, .logical_min = 1, .logical_max = 127, .physical_min = -128,
2994 .physical_max = 127, .units = 0xe, .units_exp = -3
2997 .usage_page = 0x01, .bit_size = 0x08, .report_count = 0x1, .start_byte = 0x2, .total_bits = 0x08,
2998 .bit_field = 0x003, .end_byte = 0x3, .link_usage_page = 0x01, .link_usage = 0x04, .flags = 0x8a,
2999 .usage_min = 0x31, .usage_max = 0x31, .designator_min = 1, .designator_max = 4, .data_index_min = 0x01,
3000 .data_index_max = 0x01, .logical_min = 1, .logical_max = 127, .physical_min = -128, .physical_max = 127
3003 .usage_page = 0x01, .bit_size = 0x08, .report_count = 0x1, .start_byte = 0x3, .total_bits = 0x08,
3004 .bit_field = 0x006, .end_byte = 0x4, .link_usage_page = 0x01, .link_usage = 0x04, .usage_min = 0x32,
3005 .usage_max = 0x32, .data_index_min = 0x02, .data_index_max = 0x02, .logical_min = 1, .logical_max = 127,
3006 .physical_min = -128, .physical_max = 127
3009 .usage_page = 0x01, .bit_size = 0x10, .report_count = 0x1, .start_byte = 0x6, .total_bits = 0x10,
3010 .bit_field = 0x042, .end_byte = 0x8, .link_usage_page = 0x01, .link_usage = 0x04, .flags = 0x08,
3011 .usage_min = 0x34, .usage_max = 0x34, .data_index_min = 0x03, .data_index_max = 0x03, .null_value = 1,
3012 .logical_min = 7, .logical_max = 127, .physical_min = -128, .physical_max = 127
3015 .usage_page = 0x01, .bit_size = 0x10, .report_count = 0x1, .start_byte = 0x4, .total_bits = 0x10,
3016 .bit_field = 0x042, .end_byte = 0x6, .link_usage_page = 0x01, .link_usage = 0x04, .flags = 0x08,
3017 .usage_min = 0x33, .usage_max = 0x33, .data_index_min = 0x04, .data_index_max = 0x04, .null_value = 1,
3018 .logical_min = 7, .logical_max = 127, .physical_min = -128, .physical_max = 127
3021 .usage_page = 0x09, .start_bit = 1, .bit_size = 0x01, .report_count = 0x7, .start_byte = 0x8, .total_bits = 0x07,
3022 .bit_field = 0x002, .end_byte = 0x9, .link_collection = 1, .link_usage_page = 0x01, .flags = 0x0c,
3023 .usage_min = 0x02, .usage_max = 0x02, .data_index_min = 0x05, .data_index_max = 0x05,
3026 .usage_page = 0x09, .bit_size = 0x01, .report_count = 0x1, .start_byte = 0x8, .total_bits = 0x01,
3027 .bit_field = 0x002, .end_byte = 0x9, .link_collection = 1, .link_usage_page = 0x01, .flags = 0x0c,
3028 .usage_min = 0x01, .usage_max = 0x01, .data_index_min = 0x06, .data_index_max = 0x06,
3031 .usage_page = 0x09, .bit_size = 0x08, .report_count = 0x1, .start_byte = 0x9, .total_bits = 0x08,
3032 .bit_field = 0x000, .end_byte = 0xa, .link_collection = 1, .link_usage_page = 0x01, .flags = 0x1c,
3033 .usage_min = 0x03, .usage_max = 0x08, .data_index_min = 0x07, .data_index_max = 0x0c, .null_value = 3,
3034 .logical_min = 8
3037 .usage_page = 0x09, .bit_size = 0x08, .report_count = 0x4, .start_byte = 0xa, .total_bits = 0x20,
3038 .bit_field = 0x100, .end_byte = 0xe, .link_collection = 1, .link_usage_page = 0x01, .flags = 0x1c,
3039 .usage_min = 0x09, .usage_max = 0x0c, .data_index_min = 0x0d, .data_index_max = 0x10, .null_value = 9,
3040 .logical_min = 12
3043 .usage_page = 0x09, .bit_size = 0x08, .report_count = 0x1, .start_byte = 0xe, .total_bits = 0x08,
3044 .bit_field = 0x000, .end_byte = 0xf, .link_collection = 1, .link_usage_page = 0x01, .flags = 0x0d,
3045 .usage_min = 0x10, .usage_max = 0x10, .data_index_min = 0x14, .data_index_max = 0x14, .null_value = 13,
3046 .logical_min = 16
3049 .usage_page = 0x09, .bit_size = 0x08, .report_count = 0x1, .start_byte = 0xe, .total_bits = 0x08,
3050 .bit_field = 0x000, .end_byte = 0xf, .link_collection = 1, .link_usage_page = 0x01, .flags = 0x0d,
3051 .usage_min = 0x0f, .usage_max = 0x0f, .data_index_min = 0x13, .data_index_max = 0x13, .null_value = 13,
3052 .logical_min = 16
3055 .usage_page = 0x09, .bit_size = 0x08, .report_count = 0x1, .start_byte = 0xe, .total_bits = 0x08,
3056 .bit_field = 0x000, .end_byte = 0xf, .link_collection = 1, .link_usage_page = 0x01, .flags = 0x0d,
3057 .usage_min = 0x0e, .usage_max = 0x0e, .data_index_min = 0x12, .data_index_max = 0x12, .null_value = 13,
3058 .logical_min = 16
3061 .usage_page = 0x09, .bit_size = 0x08, .report_count = 0x1, .start_byte = 0xe, .total_bits = 0x08,
3062 .bit_field = 0x000, .end_byte = 0xf, .link_collection = 1, .link_usage_page = 0x01, .flags = 0x0c,
3063 .usage_min = 0x0d, .usage_max = 0x0d, .data_index_min = 0x11, .data_index_max = 0x11, .null_value = 13,
3064 .logical_min = 16
3067 .usage_page = 0x01, .bit_size = 0x10, .report_count = 0x1, .start_byte = 0x1, .total_bits = 0x10,
3068 .bit_field = 0x002, .end_byte = 0x3, .link_usage_page = 0x01, .link_usage = 0x04, .flags = 0x08,
3069 .usage_min = 0x36, .usage_max = 0x36, .logical_min = 1, .logical_max = 127, .physical_min = -128,
3070 .physical_max = 127
3075 static const struct hidp_kdr_node expect_nodes[] =
3078 .usage = 0x04,
3079 .usage_page = 0x01,
3080 .parent = 0,
3081 .number_of_children = 0x1,
3082 .next_sibling = 0,
3083 .first_child = 0x1,
3084 .collection_type = 0x1,
3087 .usage = 0x00,
3088 .usage_page = 0x01,
3089 .parent = 0,
3090 .number_of_children = 0,
3091 .next_sibling = 0,
3092 .first_child = 0,
3093 .collection_type = 0x1,
3097 char buffer[FIELD_OFFSET( SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath[MAX_PATH] )];
3098 SP_DEVICE_INTERFACE_DATA iface = {sizeof(SP_DEVICE_INTERFACE_DATA)};
3099 SP_DEVICE_INTERFACE_DETAIL_DATA_W *iface_detail = (void *)buffer;
3100 SP_DEVINFO_DATA device = {sizeof(SP_DEVINFO_DATA)};
3101 WCHAR cwd[MAX_PATH], tempdir[MAX_PATH];
3102 PHIDP_PREPARSED_DATA preparsed_data;
3103 DWORD i, report_id = 0, polled = 0;
3104 struct hidp_kdr *kdr;
3105 LSTATUS status;
3106 HDEVINFO set;
3107 HANDLE file;
3108 HKEY hkey;
3109 BOOL ret;
3111 GetCurrentDirectoryW( ARRAY_SIZE(cwd), cwd );
3112 GetTempPathW( ARRAY_SIZE(tempdir), tempdir );
3113 SetCurrentDirectoryW( tempdir );
3115 status = RegCreateKeyExW( HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Services\\winetest",
3116 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL );
3117 ok( !status, "RegCreateKeyExW returned %#x\n", status );
3119 status = RegSetValueExW( hkey, L"ReportID", 0, REG_DWORD, (void *)&report_id, sizeof(report_id) );
3120 ok( !status, "RegSetValueExW returned %#x\n", status );
3122 status = RegSetValueExW( hkey, L"PolledMode", 0, REG_DWORD, (void *)&polled, sizeof(polled) );
3123 ok( !status, "RegSetValueExW returned %#x\n", status );
3125 status = RegSetValueExW( hkey, L"Descriptor", 0, REG_BINARY, (void *)report_desc, sizeof(report_desc) );
3126 ok( !status, "RegSetValueExW returned %#x\n", status );
3128 status = RegSetValueExW( hkey, L"Attributes", 0, REG_BINARY, (void *)&attributes, sizeof(attributes) );
3129 ok( !status, "RegSetValueExW returned %#x\n", status );
3131 status = RegSetValueExW( hkey, L"Caps", 0, REG_BINARY, (void *)&expect_hidp_caps, sizeof(expect_hidp_caps) );
3132 ok( !status, "RegSetValueExW returned %#x\n", status );
3134 status = RegSetValueExW( hkey, L"Expect", 0, REG_BINARY, NULL, 0 );
3135 ok( !status, "RegSetValueExW returned %#x\n", status );
3137 status = RegSetValueExW( hkey, L"Input", 0, REG_BINARY, NULL, 0 );
3138 ok( !status, "RegSetValueExW returned %#x\n", status );
3140 if (!pnp_driver_start( L"driver_hid.dll" )) goto done;
3142 set = SetupDiGetClassDevsW( &GUID_DEVINTERFACE_HID, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT );
3143 ok( set != INVALID_HANDLE_VALUE, "failed to get device list, error %#x\n", GetLastError() );
3144 for (i = 0; SetupDiEnumDeviceInfo( set, i, &device ); ++i)
3146 ret = SetupDiEnumDeviceInterfaces( set, &device, &GUID_DEVINTERFACE_HID, 0, &iface );
3147 ok( ret, "failed to get interface, error %#x\n", GetLastError() );
3148 ok( IsEqualGUID( &iface.InterfaceClassGuid, &GUID_DEVINTERFACE_HID ), "wrong class %s\n",
3149 debugstr_guid( &iface.InterfaceClassGuid ) );
3150 ok( iface.Flags == SPINT_ACTIVE, "got flags %#x\n", iface.Flags );
3152 iface_detail->cbSize = sizeof(*iface_detail);
3153 ret = SetupDiGetDeviceInterfaceDetailW( set, &iface, iface_detail, sizeof(buffer), NULL, NULL );
3154 ok( ret, "failed to get interface path, error %#x\n", GetLastError() );
3156 if (wcsstr( iface_detail->DevicePath, L"\\\\?\\hid#winetest#1" )) break;
3158 SetupDiDestroyDeviceInfoList( set );
3160 file = CreateFileW( iface_detail->DevicePath, FILE_READ_ACCESS | FILE_WRITE_ACCESS,
3161 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
3162 ok( file != INVALID_HANDLE_VALUE, "got error %u\n", GetLastError() );
3164 ret = HidD_GetPreparsedData( file, &preparsed_data );
3165 ok( ret, "HidD_GetPreparsedData failed with error %u\n", GetLastError() );
3167 kdr = (struct hidp_kdr *)preparsed_data;
3168 ok( !strncmp( kdr->magic, expect_kdr.magic, 8 ), "got %s expected %s\n",
3169 debugstr_an(kdr->magic, 8), debugstr_an(expect_kdr.magic, 8) );
3171 if (!strncmp( kdr->magic, expect_kdr.magic, 8 ))
3173 check_member( *kdr, expect_kdr, "%04x", usage );
3174 check_member( *kdr, expect_kdr, "%04x", usage_page );
3175 check_member( *kdr, expect_kdr, "%#x", unknown[0] );
3176 check_member( *kdr, expect_kdr, "%#x", unknown[1] );
3177 check_member( *kdr, expect_kdr, "%d", input_caps_start );
3178 check_member( *kdr, expect_kdr, "%d", input_caps_count );
3179 check_member( *kdr, expect_kdr, "%d", input_caps_end );
3180 check_member( *kdr, expect_kdr, "%d", input_report_byte_length );
3181 check_member( *kdr, expect_kdr, "%d", output_caps_start );
3182 check_member( *kdr, expect_kdr, "%d", output_caps_count );
3183 check_member( *kdr, expect_kdr, "%d", output_caps_end );
3184 check_member( *kdr, expect_kdr, "%d", output_report_byte_length );
3185 check_member( *kdr, expect_kdr, "%d", feature_caps_start );
3186 todo_wine
3187 check_member( *kdr, expect_kdr, "%d", feature_caps_count );
3188 check_member( *kdr, expect_kdr, "%d", feature_caps_end );
3189 check_member( *kdr, expect_kdr, "%d", feature_report_byte_length );
3190 todo_wine
3191 check_member( *kdr, expect_kdr, "%d", caps_size );
3192 check_member( *kdr, expect_kdr, "%d", number_link_collection_nodes );
3194 for (i = 0; i < min( ARRAY_SIZE(expect_caps), kdr->caps_size / sizeof(struct hidp_kdr_caps) ); ++i)
3196 winetest_push_context( "caps[%d]", i );
3197 check_member( kdr->caps[i], expect_caps[i], "%04x", usage_page );
3198 check_member( kdr->caps[i], expect_caps[i], "%d", report_id );
3199 check_member( kdr->caps[i], expect_caps[i], "%d", start_bit );
3200 check_member( kdr->caps[i], expect_caps[i], "%d", bit_size );
3201 check_member( kdr->caps[i], expect_caps[i], "%d", report_count );
3202 check_member( kdr->caps[i], expect_caps[i], "%d", start_byte );
3203 check_member( kdr->caps[i], expect_caps[i], "%d", total_bits );
3204 check_member( kdr->caps[i], expect_caps[i], "%#x", bit_field );
3205 check_member( kdr->caps[i], expect_caps[i], "%d", end_byte );
3206 check_member( kdr->caps[i], expect_caps[i], "%d", link_collection );
3207 check_member( kdr->caps[i], expect_caps[i], "%04x", link_usage_page );
3208 check_member( kdr->caps[i], expect_caps[i], "%04x", link_usage );
3209 check_member( kdr->caps[i], expect_caps[i], "%#x", flags );
3210 check_member( kdr->caps[i], expect_caps[i], "%#x", padding[0] );
3211 check_member( kdr->caps[i], expect_caps[i], "%#x", padding[1] );
3212 check_member( kdr->caps[i], expect_caps[i], "%#x", padding[2] );
3213 check_member( kdr->caps[i], expect_caps[i], "%#x", padding[3] );
3214 check_member( kdr->caps[i], expect_caps[i], "%#x", padding[4] );
3215 check_member( kdr->caps[i], expect_caps[i], "%#x", padding[5] );
3216 check_member( kdr->caps[i], expect_caps[i], "%#x", padding[6] );
3217 check_member( kdr->caps[i], expect_caps[i], "%#x", padding[7] );
3218 check_member( kdr->caps[i], expect_caps[i], "%04x", usage_min );
3219 check_member( kdr->caps[i], expect_caps[i], "%04x", usage_max );
3220 check_member( kdr->caps[i], expect_caps[i], "%d", string_min );
3221 check_member( kdr->caps[i], expect_caps[i], "%d", string_max );
3222 check_member( kdr->caps[i], expect_caps[i], "%d", designator_min );
3223 check_member( kdr->caps[i], expect_caps[i], "%d", designator_max );
3224 check_member( kdr->caps[i], expect_caps[i], "%#x", data_index_min );
3225 check_member( kdr->caps[i], expect_caps[i], "%#x", data_index_max );
3226 check_member( kdr->caps[i], expect_caps[i], "%d", null_value );
3227 check_member( kdr->caps[i], expect_caps[i], "%d", unknown );
3228 check_member( kdr->caps[i], expect_caps[i], "%d", logical_min );
3229 check_member( kdr->caps[i], expect_caps[i], "%d", logical_max );
3230 check_member( kdr->caps[i], expect_caps[i], "%d", physical_min );
3231 check_member( kdr->caps[i], expect_caps[i], "%d", physical_max );
3232 check_member( kdr->caps[i], expect_caps[i], "%#x", units );
3233 check_member( kdr->caps[i], expect_caps[i], "%#x", units_exp );
3234 winetest_pop_context();
3237 for (i = 0; i < ARRAY_SIZE(expect_nodes); ++i)
3239 struct hidp_kdr_node *nodes = (struct hidp_kdr_node *)((char *)kdr->caps + kdr->caps_size);
3240 winetest_push_context( "nodes[%d]", i );
3241 check_member( nodes[i], expect_nodes[i], "%04x", usage );
3242 check_member( nodes[i], expect_nodes[i], "%04x", usage_page );
3243 check_member( nodes[i], expect_nodes[i], "%d", parent );
3244 check_member( nodes[i], expect_nodes[i], "%d", number_of_children );
3245 check_member( nodes[i], expect_nodes[i], "%d", next_sibling );
3246 check_member( nodes[i], expect_nodes[i], "%d", first_child );
3247 check_member( nodes[i], expect_nodes[i], "%#x", collection_type );
3248 winetest_pop_context();
3252 HidD_FreePreparsedData( preparsed_data );
3254 CloseHandle( file );
3256 done:
3257 pnp_driver_stop();
3258 SetCurrentDirectoryW( cwd );
3261 static void cleanup_registry_keys(void)
3263 static const WCHAR joystick_oem_path[] = L"System\\CurrentControlSet\\Control\\MediaProperties\\"
3264 "PrivateProperties\\Joystick\\OEM";
3265 static const WCHAR dinput_path[] = L"System\\CurrentControlSet\\Control\\MediaProperties\\"
3266 "PrivateProperties\\DirectInput";
3267 HKEY root_key;
3269 /* These keys are automatically created by DInput and they store the
3270 list of supported force-feedback effects. OEM drivers are supposed
3271 to provide a list in HKLM for the vendor-specific force-feedback
3272 support.
3274 We need to clean them up, or DInput will not refresh the list of
3275 effects from the PID report changes.
3277 RegCreateKeyExW( HKEY_CURRENT_USER, joystick_oem_path, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &root_key, NULL );
3278 RegDeleteTreeW( root_key, expect_vidpid_str );
3279 RegCloseKey( root_key );
3281 RegCreateKeyExW( HKEY_CURRENT_USER, dinput_path, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &root_key, NULL );
3282 RegDeleteTreeW( root_key, expect_vidpid_str );
3283 RegCloseKey( root_key );
3285 RegCreateKeyExW( HKEY_LOCAL_MACHINE, joystick_oem_path, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &root_key, NULL );
3286 RegDeleteTreeW( root_key, expect_vidpid_str );
3287 RegCloseKey( root_key );
3289 RegCreateKeyExW( HKEY_LOCAL_MACHINE, dinput_path, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &root_key, NULL );
3290 RegDeleteTreeW( root_key, expect_vidpid_str );
3291 RegCloseKey( root_key );
3294 static BOOL dinput_driver_start( const BYTE *desc_buf, ULONG desc_len, const HIDP_CAPS *caps,
3295 struct hid_expect *expect, ULONG expect_size )
3297 static const HID_DEVICE_ATTRIBUTES attributes =
3299 .Size = sizeof(HID_DEVICE_ATTRIBUTES),
3300 .VendorID = LOWORD( EXPECT_VIDPID ),
3301 .ProductID = HIWORD( EXPECT_VIDPID ),
3302 .VersionNumber = 0x0100,
3304 DWORD report_id = 1;
3305 DWORD polled = 0;
3306 LSTATUS status;
3307 HKEY hkey;
3309 status = RegCreateKeyExW( HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Services\\winetest",
3310 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL );
3311 ok( !status, "RegCreateKeyExW returned %#x\n", status );
3312 status = RegSetValueExW( hkey, L"ReportID", 0, REG_DWORD, (void *)&report_id, sizeof(report_id) );
3313 ok( !status, "RegSetValueExW returned %#x\n", status );
3314 status = RegSetValueExW( hkey, L"PolledMode", 0, REG_DWORD, (void *)&polled, sizeof(polled) );
3315 ok( !status, "RegSetValueExW returned %#x\n", status );
3316 status = RegSetValueExW( hkey, L"Descriptor", 0, REG_BINARY, (void *)desc_buf, desc_len );
3317 ok( !status, "RegSetValueExW returned %#x\n", status );
3318 status = RegSetValueExW( hkey, L"Attributes", 0, REG_BINARY, (void *)&attributes, sizeof(attributes) );
3319 ok( !status, "RegSetValueExW returned %#x\n", status );
3320 status = RegSetValueExW( hkey, L"Caps", 0, REG_BINARY, (void *)caps, sizeof(*caps) );
3321 ok( !status, "RegSetValueExW returned %#x\n", status );
3322 status = RegSetValueExW( hkey, L"Expect", 0, REG_BINARY, (void *)expect, expect_size );
3323 ok( !status, "RegSetValueExW returned %#x\n", status );
3324 status = RegSetValueExW( hkey, L"Input", 0, REG_BINARY, NULL, 0 );
3325 ok( !status, "RegSetValueExW returned %#x\n", status );
3327 return pnp_driver_start( L"driver_hid.dll" );
3330 static BOOL CALLBACK find_test_device( const DIDEVICEINSTANCEW *devinst, void *context )
3332 if (IsEqualGUID( &devinst->guidProduct, &expect_guid_product ))
3333 *(DIDEVICEINSTANCEW *)context = *devinst;
3334 return DIENUM_CONTINUE;
3337 struct check_objects_todos
3339 BOOL type;
3340 BOOL guid;
3341 BOOL usage;
3342 BOOL name;
3345 struct check_objects_params
3347 DWORD version;
3348 UINT index;
3349 UINT expect_count;
3350 const DIDEVICEOBJECTINSTANCEW *expect_objs;
3351 const struct check_objects_todos *todo_objs;
3352 BOOL todo_extra;
3355 static BOOL CALLBACK check_objects( const DIDEVICEOBJECTINSTANCEW *obj, void *args )
3357 static const DIDEVICEOBJECTINSTANCEW unexpected_obj = {0};
3358 static const struct check_objects_todos todo_none = {0};
3359 struct check_objects_params *params = args;
3360 const DIDEVICEOBJECTINSTANCEW *exp = params->expect_objs + params->index;
3361 const struct check_objects_todos *todo;
3363 if (!params->todo_objs) todo = &todo_none;
3364 else todo = params->todo_objs + params->index;
3366 todo_wine_if( params->todo_extra && params->index >= params->expect_count )
3367 ok( params->index < params->expect_count, "unexpected extra object\n" );
3368 if (params->index >= params->expect_count) return DIENUM_STOP;
3370 winetest_push_context( "obj[%d]", params->index );
3372 ok( params->index < params->expect_count, "unexpected extra object\n" );
3373 if (params->index >= params->expect_count) exp = &unexpected_obj;
3375 check_member( *obj, *exp, "%u", dwSize );
3376 todo_wine_if( todo->guid )
3377 check_member_guid( *obj, *exp, guidType );
3378 todo_wine_if( params->version < 0x700 && (obj->dwType & DIDFT_BUTTON) )
3379 check_member( *obj, *exp, "%#x", dwOfs );
3380 todo_wine_if( todo->type )
3381 check_member( *obj, *exp, "%#x", dwType );
3382 check_member( *obj, *exp, "%#x", dwFlags );
3383 if (!localized) todo_wine_if( todo->name )check_member_wstr( *obj, *exp, tszName );
3384 check_member( *obj, *exp, "%u", dwFFMaxForce );
3385 check_member( *obj, *exp, "%u", dwFFForceResolution );
3386 check_member( *obj, *exp, "%u", wCollectionNumber );
3387 check_member( *obj, *exp, "%u", wDesignatorIndex );
3388 check_member( *obj, *exp, "%#04x", wUsagePage );
3389 todo_wine_if( todo->usage )
3390 check_member( *obj, *exp, "%#04x", wUsage );
3391 check_member( *obj, *exp, "%#04x", dwDimension );
3392 check_member( *obj, *exp, "%#04x", wExponent );
3393 check_member( *obj, *exp, "%u", wReportId );
3395 winetest_pop_context();
3397 params->index++;
3398 return DIENUM_CONTINUE;
3401 static BOOL CALLBACK check_object_count( const DIDEVICEOBJECTINSTANCEW *obj, void *args )
3403 DWORD *count = args;
3404 *count = *count + 1;
3405 return DIENUM_CONTINUE;
3408 struct check_effects_params
3410 UINT index;
3411 UINT expect_count;
3412 const DIEFFECTINFOW *expect_effects;
3415 static BOOL CALLBACK check_effects( const DIEFFECTINFOW *effect, void *args )
3417 static const DIEFFECTINFOW unexpected_effect = {0};
3418 struct check_effects_params *params = args;
3419 const DIEFFECTINFOW *exp = params->expect_effects + params->index;
3421 winetest_push_context( "effect[%d]", params->index );
3423 ok( params->index < params->expect_count, "unexpected extra object\n" );
3424 if (params->index >= params->expect_count) exp = &unexpected_effect;
3426 check_member( *effect, *exp, "%u", dwSize );
3427 check_member_guid( *effect, *exp, guid );
3428 check_member( *effect, *exp, "%#x", dwEffType );
3429 check_member( *effect, *exp, "%#x", dwStaticParams );
3430 check_member( *effect, *exp, "%#x", dwDynamicParams );
3431 check_member_wstr( *effect, *exp, tszName );
3433 winetest_pop_context();
3434 params->index++;
3436 return DIENUM_CONTINUE;
3439 static BOOL CALLBACK check_effect_count( const DIEFFECTINFOW *effect, void *args )
3441 DWORD *count = args;
3442 *count = *count + 1;
3443 return DIENUM_CONTINUE;
3446 static BOOL CALLBACK check_no_created_effect_objects( IDirectInputEffect *effect, void *context )
3448 ok( 0, "unexpected effect %p\n", effect );
3449 return DIENUM_CONTINUE;
3452 struct check_created_effect_params
3454 IDirectInputEffect *expect_effect;
3455 DWORD count;
3458 static BOOL CALLBACK check_created_effect_objects( IDirectInputEffect *effect, void *context )
3460 struct check_created_effect_params *params = context;
3461 ULONG ref;
3463 ok( effect == params->expect_effect, "got effect %p, expected %p\n", effect, params->expect_effect );
3464 params->count++;
3466 IDirectInputEffect_AddRef( effect );
3467 ref = IDirectInputEffect_Release( effect );
3468 ok( ref == 1, "got ref %u, expected 1\n", ref );
3469 return DIENUM_CONTINUE;
3472 static BOOL CALLBACK enum_device_count( const DIDEVICEINSTANCEW *devinst, void *context )
3474 DWORD *count = context;
3475 *count = *count + 1;
3476 return DIENUM_CONTINUE;
3479 static HRESULT create_dinput_device( DWORD version, DIDEVICEINSTANCEW *devinst, IDirectInputDevice8W **device )
3481 DIPROPDWORD prop_dword =
3483 .diph =
3485 .dwSize = sizeof(DIPROPDWORD),
3486 .dwHeaderSize = sizeof(DIPROPHEADER),
3487 .dwHow = DIPH_DEVICE,
3490 IDirectInput8W *di8;
3491 IDirectInputW *di;
3492 ULONG ref, count;
3493 HRESULT hr;
3495 if (version >= 0x800)
3497 hr = DirectInput8Create( instance, version, &IID_IDirectInput8W, (void **)&di8, NULL );
3498 if (FAILED(hr))
3500 win_skip( "DirectInput8Create returned %#x\n", hr );
3501 return hr;
3504 hr = IDirectInput8_EnumDevices( di8, DI8DEVCLASS_ALL, find_test_device, devinst, DIEDFL_ALLDEVICES );
3505 ok( hr == DI_OK, "EnumDevices returned: %#x\n", hr );
3506 if (!IsEqualGUID( &devinst->guidProduct, &expect_guid_product ))
3508 win_skip( "device not found, skipping tests\n" );
3509 ref = IDirectInput8_Release( di8 );
3510 ok( ref == 0, "Release returned %d\n", ref );
3511 return DIERR_DEVICENOTREG;
3514 hr = IDirectInput8_EnumDevices( di8, DI8DEVCLASS_ALL, NULL, NULL, DIEDFL_ALLDEVICES );
3515 ok( hr == DIERR_INVALIDPARAM, "EnumDevices returned: %#x\n", hr );
3516 hr = IDirectInput8_EnumDevices( di8, DI8DEVCLASS_ALL, enum_device_count, &count, 0xdeadbeef );
3517 ok( hr == DIERR_INVALIDPARAM, "EnumDevices returned: %#x\n", hr );
3518 hr = IDirectInput8_EnumDevices( di8, 0xdeadbeef, enum_device_count, &count, DIEDFL_ALLDEVICES );
3519 ok( hr == DIERR_INVALIDPARAM, "EnumDevices returned: %#x\n", hr );
3521 count = 0;
3522 hr = IDirectInput8_EnumDevices( di8, DI8DEVCLASS_ALL, enum_device_count, &count, DIEDFL_ALLDEVICES );
3523 ok( hr == DI_OK, "EnumDevices returned: %#x\n", hr );
3524 ok( count == 3, "got count %u, expected 0\n", count );
3525 count = 0;
3526 hr = IDirectInput8_EnumDevices( di8, DI8DEVCLASS_DEVICE, enum_device_count, &count, DIEDFL_ALLDEVICES );
3527 ok( hr == DI_OK, "EnumDevices returned: %#x\n", hr );
3528 ok( count == 0, "got count %u, expected 0\n", count );
3529 count = 0;
3530 hr = IDirectInput8_EnumDevices( di8, DI8DEVCLASS_POINTER, enum_device_count, &count,
3531 DIEDFL_INCLUDEALIASES | DIEDFL_INCLUDEPHANTOMS | DIEDFL_INCLUDEHIDDEN );
3532 ok( hr == DI_OK, "EnumDevices returned: %#x\n", hr );
3533 todo_wine
3534 ok( count == 3, "got count %u, expected 3\n", count );
3535 count = 0;
3536 hr = IDirectInput8_EnumDevices( di8, DI8DEVCLASS_KEYBOARD, enum_device_count, &count,
3537 DIEDFL_INCLUDEALIASES | DIEDFL_INCLUDEPHANTOMS | DIEDFL_INCLUDEHIDDEN );
3538 ok( hr == DI_OK, "EnumDevices returned: %#x\n", hr );
3539 todo_wine
3540 ok( count == 3, "got count %u, expected 3\n", count );
3541 count = 0;
3542 hr = IDirectInput8_EnumDevices( di8, DI8DEVCLASS_GAMECTRL, enum_device_count, &count,
3543 DIEDFL_INCLUDEALIASES | DIEDFL_INCLUDEPHANTOMS | DIEDFL_INCLUDEHIDDEN );
3544 ok( hr == DI_OK, "EnumDevices returned: %#x\n", hr );
3545 ok( count == 1, "got count %u, expected 1\n", count );
3547 count = 0;
3548 hr = IDirectInput8_EnumDevices( di8, (devinst->dwDevType & 0xff), enum_device_count, &count, DIEDFL_ALLDEVICES );
3549 ok( hr == DI_OK, "EnumDevices returned: %#x\n", hr );
3550 ok( count == 1, "got count %u, expected 1\n", count );
3552 count = 0;
3553 hr = IDirectInput8_EnumDevices( di8, (devinst->dwDevType & 0xff), enum_device_count, &count, DIEDFL_FORCEFEEDBACK );
3554 ok( hr == DI_OK, "EnumDevices returned: %#x\n", hr );
3555 if (IsEqualGUID( &devinst->guidFFDriver, &GUID_NULL )) ok( count == 0, "got count %u, expected 0\n", count );
3556 else ok( count == 1, "got count %u, expected 1\n", count );
3558 count = 0;
3559 hr = IDirectInput8_EnumDevices( di8, (devinst->dwDevType & 0xff) + 1, enum_device_count, &count, DIEDFL_ALLDEVICES );
3560 if ((devinst->dwDevType & 0xff) != DI8DEVTYPE_SUPPLEMENTAL) ok( hr == DI_OK, "EnumDevices returned: %#x\n", hr );
3561 else ok( hr == DIERR_INVALIDPARAM, "EnumDevices returned: %#x\n", hr );
3562 ok( count == 0, "got count %u, expected 0\n", count );
3564 hr = IDirectInput8_CreateDevice( di8, &devinst->guidInstance, NULL, NULL );
3565 ok( hr == E_POINTER, "CreateDevice returned %#x\n", hr );
3566 hr = IDirectInput8_CreateDevice( di8, NULL, device, NULL );
3567 ok( hr == E_POINTER, "CreateDevice returned %#x\n", hr );
3568 hr = IDirectInput8_CreateDevice( di8, &GUID_NULL, device, NULL );
3569 ok( hr == DIERR_DEVICENOTREG, "CreateDevice returned %#x\n", hr );
3570 hr = IDirectInput8_CreateDevice( di8, &devinst->guidInstance, device, NULL );
3571 ok( hr == DI_OK, "CreateDevice returned %#x\n", hr );
3573 prop_dword.dwData = 0xdeadbeef;
3574 hr = IDirectInputDevice8_GetProperty( *device, DIPROP_VIDPID, &prop_dword.diph );
3575 ok( hr == DI_OK, "GetProperty DIPROP_VIDPID returned %#x\n", hr );
3576 /* Wine may get the wrong device here, because the test driver creates another instance of
3577 hidclass.sys, and gets duplicate rawinput handles, which we use in the guidInstance */
3578 todo_wine_if( prop_dword.dwData != EXPECT_VIDPID )
3579 ok( prop_dword.dwData == EXPECT_VIDPID, "got %#x expected %#x\n", prop_dword.dwData, EXPECT_VIDPID );
3581 ref = IDirectInputDevice8_Release( *device );
3582 ok( ref == 0, "Release returned %d\n", ref );
3584 hr = IDirectInput8_CreateDevice( di8, &expect_guid_product, device, NULL );
3585 ok( hr == DI_OK, "CreateDevice returned %#x\n", hr );
3587 ref = IDirectInput8_Release( di8 );
3588 todo_wine
3589 ok( ref == 0, "Release returned %d\n", ref );
3591 else
3593 hr = DirectInputCreateEx( instance, version, &IID_IDirectInput2W, (void **)&di, NULL );
3594 if (FAILED(hr))
3596 win_skip( "DirectInputCreateEx returned %#x\n", hr );
3597 return hr;
3600 hr = IDirectInput_EnumDevices( di, 0, find_test_device, devinst, DIEDFL_ALLDEVICES );
3601 ok( hr == DI_OK, "EnumDevices returned: %#x\n", hr );
3602 if (!IsEqualGUID( &devinst->guidProduct, &expect_guid_product ))
3604 win_skip( "device not found, skipping tests\n" );
3606 ref = IDirectInput_Release( di );
3607 ok( ref == 0, "Release returned %d\n", ref );
3608 return DIERR_DEVICENOTREG;
3611 hr = IDirectInput_EnumDevices( di, 0, NULL, NULL, DIEDFL_ALLDEVICES );
3612 ok( hr == DIERR_INVALIDPARAM, "EnumDevices returned: %#x\n", hr );
3613 hr = IDirectInput_EnumDevices( di, 0, enum_device_count, &count, 0xdeadbeef );
3614 ok( hr == DIERR_INVALIDPARAM, "EnumDevices returned: %#x\n", hr );
3615 hr = IDirectInput_EnumDevices( di, 0xdeadbeef, enum_device_count, &count, DIEDFL_ALLDEVICES );
3616 ok( hr == DIERR_INVALIDPARAM, "EnumDevices returned: %#x\n", hr );
3617 hr = IDirectInput_EnumDevices( di, 0, enum_device_count, &count, DIEDFL_INCLUDEHIDDEN );
3618 ok( hr == DIERR_INVALIDPARAM, "EnumDevices returned: %#x\n", hr );
3620 count = 0;
3621 hr = IDirectInput_EnumDevices( di, 0, enum_device_count, &count, DIEDFL_ALLDEVICES );
3622 ok( hr == DI_OK, "EnumDevices returned: %#x\n", hr );
3623 ok( count == 3, "got count %u, expected 0\n", count );
3624 count = 0;
3625 hr = IDirectInput_EnumDevices( di, DIDEVTYPE_DEVICE, enum_device_count, &count, DIEDFL_ALLDEVICES );
3626 ok( hr == DI_OK, "EnumDevices returned: %#x\n", hr );
3627 ok( count == 0, "got count %u, expected 0\n", count );
3628 count = 0;
3629 hr = IDirectInput_EnumDevices( di, DIDEVTYPE_MOUSE, enum_device_count, &count,
3630 DIEDFL_INCLUDEALIASES | DIEDFL_INCLUDEPHANTOMS );
3631 ok( hr == DI_OK, "EnumDevices returned: %#x\n", hr );
3632 todo_wine
3633 ok( count == 3, "got count %u, expected 3\n", count );
3634 count = 0;
3635 hr = IDirectInput_EnumDevices( di, DIDEVTYPE_KEYBOARD, enum_device_count, &count,
3636 DIEDFL_INCLUDEALIASES | DIEDFL_INCLUDEPHANTOMS );
3637 ok( hr == DI_OK, "EnumDevices returned: %#x\n", hr );
3638 todo_wine
3639 ok( count == 3, "got count %u, expected 3\n", count );
3640 count = 0;
3641 hr = IDirectInput_EnumDevices( di, DIDEVTYPE_JOYSTICK, enum_device_count, &count,
3642 DIEDFL_INCLUDEALIASES | DIEDFL_INCLUDEPHANTOMS );
3643 ok( hr == DI_OK, "EnumDevices returned: %#x\n", hr );
3644 ok( count == 1, "got count %u, expected 1\n", count );
3646 count = 0;
3647 hr = IDirectInput_EnumDevices( di, (devinst->dwDevType & 0xff), enum_device_count, &count, DIEDFL_ALLDEVICES );
3648 ok( hr == DI_OK, "EnumDevices returned: %#x\n", hr );
3649 ok( count == 1, "got count %u, expected 1\n", count );
3651 count = 0;
3652 hr = IDirectInput_EnumDevices( di, (devinst->dwDevType & 0xff), enum_device_count, &count, DIEDFL_FORCEFEEDBACK );
3653 ok( hr == DI_OK, "EnumDevices returned: %#x\n", hr );
3654 if (IsEqualGUID( &devinst->guidFFDriver, &GUID_NULL )) ok( count == 0, "got count %u, expected 0\n", count );
3655 else ok( count == 1, "got count %u, expected 1\n", count );
3657 hr = IDirectInput_EnumDevices( di, 0x14, enum_device_count, &count, DIEDFL_ALLDEVICES );
3658 ok( hr == DIERR_INVALIDPARAM, "EnumDevices returned: %#x\n", hr );
3660 hr = IDirectInput_CreateDevice( di, &expect_guid_product, (IDirectInputDeviceW **)device, NULL );
3661 ok( hr == DI_OK, "CreateDevice returned %#x\n", hr );
3663 ref = IDirectInput_Release( di );
3664 todo_wine
3665 ok( ref == 0, "Release returned %d\n", ref );
3668 return DI_OK;
3671 static void test_simple_joystick(void)
3673 #include "psh_hid_macros.h"
3674 static const unsigned char report_desc[] =
3676 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
3677 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
3678 COLLECTION(1, Application),
3679 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
3680 COLLECTION(1, Report),
3681 REPORT_ID(1, 1),
3683 USAGE(1, HID_USAGE_GENERIC_WHEEL),
3684 USAGE(4, (0xff01u<<16)|(0x1234)),
3685 USAGE(1, HID_USAGE_GENERIC_X),
3686 USAGE(1, HID_USAGE_GENERIC_Y),
3687 USAGE(4, (HID_USAGE_PAGE_SIMULATION<<16)|HID_USAGE_SIMULATION_RUDDER),
3688 USAGE(4, (HID_USAGE_PAGE_DIGITIZER<<16)|HID_USAGE_DIGITIZER_TIP_PRESSURE),
3689 USAGE(4, (HID_USAGE_PAGE_CONSUMER<<16)|HID_USAGE_CONSUMER_VOLUME),
3690 LOGICAL_MINIMUM(1, 0xe7),
3691 LOGICAL_MAXIMUM(1, 0x38),
3692 PHYSICAL_MINIMUM(1, 0xe7),
3693 PHYSICAL_MAXIMUM(1, 0x38),
3694 REPORT_SIZE(1, 8),
3695 REPORT_COUNT(1, 7),
3696 INPUT(1, Data|Var|Abs),
3698 USAGE(1, HID_USAGE_GENERIC_HATSWITCH),
3699 LOGICAL_MINIMUM(1, 1),
3700 LOGICAL_MAXIMUM(1, 8),
3701 PHYSICAL_MINIMUM(1, 0),
3702 PHYSICAL_MAXIMUM(1, 8),
3703 REPORT_SIZE(1, 4),
3704 REPORT_COUNT(1, 1),
3705 INPUT(1, Data|Var|Abs|Null),
3707 USAGE_PAGE(1, HID_USAGE_PAGE_BUTTON),
3708 USAGE_MINIMUM(1, 1),
3709 USAGE_MAXIMUM(1, 2),
3710 LOGICAL_MINIMUM(1, 0),
3711 LOGICAL_MAXIMUM(1, 1),
3712 PHYSICAL_MINIMUM(1, 0),
3713 PHYSICAL_MAXIMUM(1, 1),
3714 REPORT_SIZE(1, 1),
3715 REPORT_COUNT(1, 4),
3716 INPUT(1, Data|Var|Abs),
3717 END_COLLECTION,
3718 END_COLLECTION,
3720 #undef REPORT_ID_OR_USAGE_PAGE
3721 #include "pop_hid_macros.h"
3723 static const HIDP_CAPS hid_caps =
3725 .InputReportByteLength = 9,
3727 static const DIDEVCAPS expect_caps =
3729 .dwSize = sizeof(DIDEVCAPS),
3730 .dwFlags = DIDC_ATTACHED | DIDC_EMULATED,
3731 .dwDevType = DIDEVTYPE_HID | (DI8DEVTYPEJOYSTICK_LIMITED << 8) | DI8DEVTYPE_JOYSTICK,
3732 .dwAxes = 6,
3733 .dwPOVs = 1,
3734 .dwButtons = 2,
3736 struct hid_expect injected_input[] =
3739 .code = IOCTL_HID_READ_REPORT,
3740 .report_buf = {1,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0},
3743 .code = IOCTL_HID_READ_REPORT,
3744 .report_buf = {1,0x10,0x10,0x38,0x38,0x10,0x10,0x10,0xf8},
3747 .code = IOCTL_HID_READ_REPORT,
3748 .report_buf = {1,0x10,0x10,0x01,0x01,0x10,0x10,0x10,0x00},
3751 .code = IOCTL_HID_READ_REPORT,
3752 .report_buf = {1,0x10,0x10,0x01,0x01,0x10,0x10,0x10,0x00},
3755 .code = IOCTL_HID_READ_REPORT,
3756 .report_buf = {1,0x10,0x10,0x80,0x80,0x10,0x10,0x10,0xff},
3759 .code = IOCTL_HID_READ_REPORT,
3760 .report_buf = {1,0x10,0x10,0x10,0xee,0x10,0x10,0x10,0x54},
3763 static const struct DIJOYSTATE2 expect_state[] =
3765 {.lX = 32767, .lY = 32767, .lZ = 32767, .rgdwPOV = {-1, -1, -1, -1}, .rgbButtons = {0, 0}},
3766 {.lX = 32767, .lY = 32767, .lZ = 32767, .rgdwPOV = {-1, -1, -1, -1}, .rgbButtons = {0, 0}},
3767 {.lX = 65535, .lY = 65535, .lZ = 32767, .rgdwPOV = {31500, -1, -1, -1}, .rgbButtons = {0x80, 0x80}},
3768 {.lX = 20779, .lY = 20779, .lZ = 32767, .rgdwPOV = {-1, -1, -1, -1}, .rgbButtons = {0, 0}},
3769 {.lX = 20779, .lY = 20779, .lZ = 32767, .rgdwPOV = {-1, -1, -1, -1}, .rgbButtons = {0, 0}},
3770 {.lX = 0, .lY = 0, .lZ = 32767, .rgdwPOV = {-1, -1, -1, -1}, .rgbButtons = {0x80, 0x80}},
3771 {.lX = 32767, .lY = 5594, .lZ = 32767, .rgdwPOV = {13500, -1, -1, -1}, .rgbButtons = {0x80}},
3773 static const struct DIJOYSTATE2 expect_state_abs[] =
3775 {.lX = -9000, .lY = 26000, .lZ = 26000, .rgdwPOV = {-1, -1, -1, -1}, .rgbButtons = {0, 0}},
3776 {.lX = -9000, .lY = 26000, .lZ = 26000, .rgdwPOV = {-1, -1, -1, -1}, .rgbButtons = {0, 0}},
3777 {.lX = -4000, .lY = 51000, .lZ = 26000, .rgdwPOV = {31500, -1, -1, -1}, .rgbButtons = {0x80, 0x80}},
3778 {.lX = -10667, .lY = 12905, .lZ = 26000, .rgdwPOV = {-1, -1, -1, -1}, .rgbButtons = {0, 0}},
3779 {.lX = -10667, .lY = 12905, .lZ = 26000, .rgdwPOV = {-1, -1, -1, -1}, .rgbButtons = {0, 0}},
3780 {.lX = -14000, .lY = 1000, .lZ = 26000, .rgdwPOV = {-1, -1, -1, -1}, .rgbButtons = {0x80, 0x80}},
3781 {.lX = -9000, .lY = 1000, .lZ = 26000, .rgdwPOV = {13500, -1, -1, -1}, .rgbButtons = {0x80}},
3783 static const struct DIJOYSTATE2 expect_state_rel[] =
3785 {.lX = 0, .lY = 0, .rgdwPOV = {13500, -1, -1, -1}, .rgbButtons = {0x80, 0}},
3786 {.lX = 9016, .lY = -984, .lZ = -25984, .rgdwPOV = {-1, -1, -1, -1}, .rgbButtons = {0, 0}},
3787 {.lX = 40, .lY = 40, .rgdwPOV = {31500, -1, -1, -1}, .rgbButtons = {0x80, 0x80}},
3788 {.lX = -55, .lY = -55, .rgdwPOV = {-1, -1, -1, -1}, .rgbButtons = {0, 0}},
3789 {.lX = 0, .lY = 0, .rgdwPOV = {-1, -1, -1, -1}, .rgbButtons = {0, 0}},
3790 {.lX = -129, .lY = -129, .rgdwPOV = {-1, -1, -1, -1}, .rgbButtons = {0x80, 0x80}},
3791 {.lX = 144, .lY = 110, .rgdwPOV = {13500, -1, -1, -1}, .rgbButtons = {0x80}},
3793 static const DIDEVICEOBJECTDATA expect_objdata[] =
3795 {.dwOfs = 0x4, .dwData = 0xffff, .dwSequence = 0xa},
3796 {.dwOfs = 0x4, .dwData = 0xffff, .dwSequence = 0xa},
3797 {.dwOfs = 0, .dwData = 0xffff, .dwSequence = 0xa},
3798 {.dwOfs = 0x20, .dwData = 31500, .dwSequence = 0xa},
3799 {.dwOfs = 0x30, .dwData = 0x80, .dwSequence = 0xa},
3800 {.dwOfs = 0x4, .dwData = 0x512b, .dwSequence = 0xd},
3801 {.dwOfs = 0, .dwData = 0x512b, .dwSequence = 0xd},
3802 {.dwOfs = 0x20, .dwData = -1, .dwSequence = 0xd},
3803 {.dwOfs = 0x30, .dwData = 0, .dwSequence = 0xd},
3804 {.dwOfs = 0x31, .dwData = 0, .dwSequence = 0xd},
3805 {.dwOfs = 0x4, .dwData = 0, .dwSequence = 0xf},
3806 {.dwOfs = 0, .dwData = 0, .dwSequence = 0xf},
3807 {.dwOfs = 0x30, .dwData = 0x80, .dwSequence = 0xf},
3808 {.dwOfs = 0x31, .dwData = 0x80, .dwSequence = 0xf},
3811 const DIDEVICEINSTANCEW expect_devinst =
3813 .dwSize = sizeof(DIDEVICEINSTANCEW),
3814 .guidInstance = expect_guid_product,
3815 .guidProduct = expect_guid_product,
3816 .dwDevType = DIDEVTYPE_HID | (DI8DEVTYPEJOYSTICK_LIMITED << 8) | DI8DEVTYPE_JOYSTICK,
3817 .tszInstanceName = L"Wine test root driver",
3818 .tszProductName = L"Wine test root driver",
3819 .guidFFDriver = GUID_NULL,
3820 .wUsagePage = HID_USAGE_PAGE_GENERIC,
3821 .wUsage = HID_USAGE_GENERIC_JOYSTICK,
3823 const DIDEVICEOBJECTINSTANCEW expect_objects[] =
3826 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
3827 .guidType = GUID_Unknown,
3828 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(6),
3829 .tszName = L"Volume",
3830 .wCollectionNumber = 1,
3831 .wUsagePage = HID_USAGE_PAGE_CONSUMER,
3832 .wUsage = HID_USAGE_CONSUMER_VOLUME,
3833 .wReportId = 1,
3836 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
3837 .guidType = GUID_Unknown,
3838 .dwOfs = 0x4,
3839 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(7),
3840 .tszName = L"Tip Pressure",
3841 .wCollectionNumber = 1,
3842 .wUsagePage = HID_USAGE_PAGE_DIGITIZER,
3843 .wUsage = HID_USAGE_DIGITIZER_TIP_PRESSURE,
3844 .wReportId = 1,
3847 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
3848 .guidType = GUID_RzAxis,
3849 .dwOfs = 0x8,
3850 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(5),
3851 .dwFlags = DIDOI_ASPECTPOSITION,
3852 .tszName = L"Rudder",
3853 .wCollectionNumber = 1,
3854 .wUsagePage = HID_USAGE_PAGE_SIMULATION,
3855 .wUsage = HID_USAGE_SIMULATION_RUDDER,
3856 .wReportId = 1,
3859 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
3860 .guidType = GUID_YAxis,
3861 .dwOfs = 0xc,
3862 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(1),
3863 .dwFlags = DIDOI_ASPECTPOSITION,
3864 .tszName = L"Y Axis",
3865 .wCollectionNumber = 1,
3866 .wUsagePage = HID_USAGE_PAGE_GENERIC,
3867 .wUsage = HID_USAGE_GENERIC_Y,
3868 .wReportId = 1,
3871 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
3872 .guidType = GUID_XAxis,
3873 .dwOfs = 0x10,
3874 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(0),
3875 .dwFlags = DIDOI_ASPECTPOSITION,
3876 .tszName = L"X Axis",
3877 .wCollectionNumber = 1,
3878 .wUsagePage = HID_USAGE_PAGE_GENERIC,
3879 .wUsage = HID_USAGE_GENERIC_X,
3880 .wReportId = 1,
3883 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
3884 .guidType = GUID_ZAxis,
3885 .dwOfs = 0x18,
3886 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(2),
3887 .dwFlags = DIDOI_ASPECTPOSITION,
3888 .tszName = L"Wheel",
3889 .wCollectionNumber = 1,
3890 .wUsagePage = HID_USAGE_PAGE_GENERIC,
3891 .wUsage = HID_USAGE_GENERIC_WHEEL,
3892 .wReportId = 1,
3895 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
3896 .guidType = GUID_POV,
3897 .dwOfs = 0x1c,
3898 .dwType = DIDFT_POV|DIDFT_MAKEINSTANCE(0),
3899 .tszName = L"Hat Switch",
3900 .wCollectionNumber = 1,
3901 .wUsagePage = HID_USAGE_PAGE_GENERIC,
3902 .wUsage = HID_USAGE_GENERIC_HATSWITCH,
3903 .wReportId = 1,
3906 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
3907 .guidType = GUID_Button,
3908 .dwOfs = 0x20,
3909 .dwType = DIDFT_PSHBUTTON|DIDFT_MAKEINSTANCE(0),
3910 .tszName = L"Button 0",
3911 .wCollectionNumber = 1,
3912 .wUsagePage = HID_USAGE_PAGE_BUTTON,
3913 .wUsage = 0x1,
3914 .wReportId = 1,
3917 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
3918 .guidType = GUID_Button,
3919 .dwOfs = 0x21,
3920 .dwType = DIDFT_PSHBUTTON|DIDFT_MAKEINSTANCE(1),
3921 .tszName = L"Button 1",
3922 .wCollectionNumber = 1,
3923 .wUsagePage = HID_USAGE_PAGE_BUTTON,
3924 .wUsage = 0x2,
3925 .wReportId = 1,
3928 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
3929 .guidType = GUID_Unknown,
3930 .dwType = DIDFT_COLLECTION|DIDFT_NODATA|DIDFT_MAKEINSTANCE(0),
3931 .tszName = L"Collection 0 - Joystick",
3932 .wUsagePage = HID_USAGE_PAGE_GENERIC,
3933 .wUsage = HID_USAGE_GENERIC_JOYSTICK,
3936 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
3937 .guidType = GUID_Unknown,
3938 .dwType = DIDFT_COLLECTION|DIDFT_NODATA|DIDFT_MAKEINSTANCE(1),
3939 .tszName = L"Collection 1 - Joystick",
3940 .wUsagePage = HID_USAGE_PAGE_GENERIC,
3941 .wUsage = HID_USAGE_GENERIC_JOYSTICK,
3944 const DIEFFECTINFOW expect_effects[] = {};
3946 struct check_objects_params check_objects_params =
3948 .version = DIRECTINPUT_VERSION,
3949 .expect_count = ARRAY_SIZE(expect_objects),
3950 .expect_objs = expect_objects,
3952 struct check_effects_params check_effects_params =
3954 .expect_count = ARRAY_SIZE(expect_effects),
3955 .expect_effects = expect_effects,
3957 DIPROPGUIDANDPATH prop_guid_path =
3959 .diph =
3961 .dwSize = sizeof(DIPROPGUIDANDPATH),
3962 .dwHeaderSize = sizeof(DIPROPHEADER),
3963 .dwHow = DIPH_DEVICE,
3966 DIPROPSTRING prop_string =
3968 .diph =
3970 .dwSize = sizeof(DIPROPSTRING),
3971 .dwHeaderSize = sizeof(DIPROPHEADER),
3972 .dwHow = DIPH_DEVICE,
3975 DIPROPDWORD prop_dword =
3977 .diph =
3979 .dwSize = sizeof(DIPROPDWORD),
3980 .dwHeaderSize = sizeof(DIPROPHEADER),
3981 .dwHow = DIPH_DEVICE,
3984 DIPROPRANGE prop_range =
3986 .diph =
3988 .dwSize = sizeof(DIPROPRANGE),
3989 .dwHeaderSize = sizeof(DIPROPHEADER),
3990 .dwHow = DIPH_DEVICE,
3993 DIPROPPOINTER prop_pointer =
3995 .diph =
3997 .dwSize = sizeof(DIPROPPOINTER),
3998 .dwHeaderSize = sizeof(DIPROPHEADER),
4001 DIOBJECTDATAFORMAT objdataformat[32] = {{0}};
4002 WCHAR cwd[MAX_PATH], tempdir[MAX_PATH];
4003 DIDEVICEOBJECTDATA objdata[32] = {{0}};
4004 DIDEVICEOBJECTINSTANCEW objinst = {0};
4005 DIDEVICEINSTANCEW devinst = {0};
4006 DIEFFECTINFOW effectinfo = {0};
4007 DIDATAFORMAT dataformat = {0};
4008 IDirectInputDevice8W *device;
4009 IDirectInputEffect *effect;
4010 DIEFFESCAPE escape = {0};
4011 DIDEVCAPS caps = {0};
4012 HANDLE event, file;
4013 char buffer[1024];
4014 DIJOYSTATE2 state;
4015 ULONG i, res, ref;
4016 HRESULT hr;
4017 WCHAR *tmp;
4018 GUID guid;
4019 HWND hwnd;
4021 GetCurrentDirectoryW( ARRAY_SIZE(cwd), cwd );
4022 GetTempPathW( ARRAY_SIZE(tempdir), tempdir );
4023 SetCurrentDirectoryW( tempdir );
4025 cleanup_registry_keys();
4026 if (!dinput_driver_start( report_desc, sizeof(report_desc), &hid_caps, NULL, 0 )) goto done;
4027 if (FAILED(hr = create_dinput_device( DIRECTINPUT_VERSION, &devinst, &device ))) goto done;
4029 hr = IDirectInputDevice8_Initialize( device, instance, 0x0700, &GUID_NULL );
4030 todo_wine
4031 ok( hr == DIERR_BETADIRECTINPUTVERSION, "Initialize returned %#x\n", hr );
4032 hr = IDirectInputDevice8_Initialize( device, instance, DIRECTINPUT_VERSION, NULL );
4033 todo_wine
4034 ok( hr == E_POINTER, "Initialize returned %#x\n", hr );
4035 hr = IDirectInputDevice8_Initialize( device, NULL, DIRECTINPUT_VERSION, &GUID_NULL );
4036 todo_wine
4037 ok( hr == DIERR_INVALIDPARAM, "Initialize returned %#x\n", hr );
4038 hr = IDirectInputDevice8_Initialize( device, instance, DIRECTINPUT_VERSION, &GUID_NULL );
4039 todo_wine
4040 ok( hr == REGDB_E_CLASSNOTREG, "Initialize returned %#x\n", hr );
4042 hr = IDirectInputDevice8_Initialize( device, instance, DIRECTINPUT_VERSION, &devinst.guidInstance );
4043 ok( hr == DI_OK, "Initialize returned %#x\n", hr );
4044 guid = devinst.guidInstance;
4045 memset( &devinst, 0, sizeof(devinst) );
4046 devinst.dwSize = sizeof(DIDEVICEINSTANCEW);
4047 hr = IDirectInputDevice8_GetDeviceInfo( device, &devinst );
4048 ok( hr == DI_OK, "GetDeviceInfo returned %#x\n", hr );
4049 ok( IsEqualGUID( &guid, &devinst.guidInstance ), "got %s expected %s\n", debugstr_guid( &guid ),
4050 debugstr_guid( &devinst.guidInstance ) );
4051 hr = IDirectInputDevice8_Initialize( device, instance, DIRECTINPUT_VERSION, &devinst.guidProduct );
4052 ok( hr == DI_OK, "Initialize returned %#x\n", hr );
4054 hr = IDirectInputDevice8_GetDeviceInfo( device, NULL );
4055 ok( hr == E_POINTER, "GetDeviceInfo returned %#x\n", hr );
4056 devinst.dwSize = sizeof(DIDEVICEINSTANCEW) + 1;
4057 hr = IDirectInputDevice8_GetDeviceInfo( device, &devinst );
4058 ok( hr == DIERR_INVALIDPARAM, "GetDeviceInfo returned %#x\n", hr );
4060 devinst.dwSize = sizeof(DIDEVICEINSTANCE_DX3W);
4061 hr = IDirectInputDevice8_GetDeviceInfo( device, &devinst );
4062 ok( hr == DI_OK, "GetDeviceInfo returned %#x\n", hr );
4063 todo_wine
4064 check_member_guid( devinst, expect_devinst, guidInstance );
4065 check_member_guid( devinst, expect_devinst, guidProduct );
4066 check_member( devinst, expect_devinst, "%#x", dwDevType );
4067 todo_wine
4068 check_member_wstr( devinst, expect_devinst, tszInstanceName );
4069 todo_wine
4070 check_member_wstr( devinst, expect_devinst, tszProductName );
4072 memset( &devinst, 0, sizeof(devinst) );
4073 devinst.dwSize = sizeof(DIDEVICEINSTANCEW);
4074 hr = IDirectInputDevice8_GetDeviceInfo( device, &devinst );
4075 ok( hr == DI_OK, "GetDeviceInfo returned %#x\n", hr );
4076 check_member( devinst, expect_devinst, "%d", dwSize );
4077 todo_wine
4078 check_member_guid( devinst, expect_devinst, guidInstance );
4079 check_member_guid( devinst, expect_devinst, guidProduct );
4080 check_member( devinst, expect_devinst, "%#x", dwDevType );
4081 todo_wine
4082 check_member_wstr( devinst, expect_devinst, tszInstanceName );
4083 todo_wine
4084 check_member_wstr( devinst, expect_devinst, tszProductName );
4085 check_member_guid( devinst, expect_devinst, guidFFDriver );
4086 check_member( devinst, expect_devinst, "%04x", wUsagePage );
4087 check_member( devinst, expect_devinst, "%04x", wUsage );
4089 hr = IDirectInputDevice8_GetCapabilities( device, NULL );
4090 ok( hr == E_POINTER, "GetCapabilities returned %#x\n", hr );
4091 hr = IDirectInputDevice8_GetCapabilities( device, &caps );
4092 ok( hr == DIERR_INVALIDPARAM, "GetCapabilities returned %#x\n", hr );
4093 caps.dwSize = sizeof(DIDEVCAPS);
4094 hr = IDirectInputDevice8_GetCapabilities( device, &caps );
4095 ok( hr == DI_OK, "GetCapabilities returned %#x\n", hr );
4096 check_member( caps, expect_caps, "%d", dwSize );
4097 check_member( caps, expect_caps, "%#x", dwFlags );
4098 check_member( caps, expect_caps, "%#x", dwDevType );
4099 check_member( caps, expect_caps, "%d", dwAxes );
4100 check_member( caps, expect_caps, "%d", dwButtons );
4101 check_member( caps, expect_caps, "%d", dwPOVs );
4102 check_member( caps, expect_caps, "%d", dwFFSamplePeriod );
4103 check_member( caps, expect_caps, "%d", dwFFMinTimeResolution );
4104 check_member( caps, expect_caps, "%d", dwFirmwareRevision );
4105 check_member( caps, expect_caps, "%d", dwHardwareRevision );
4106 check_member( caps, expect_caps, "%d", dwFFDriverVersion );
4108 hr = IDirectInputDevice8_GetProperty( device, NULL, NULL );
4109 ok( hr == DIERR_INVALIDPARAM, "GetProperty returned %#x\n", hr );
4110 hr = IDirectInputDevice8_GetProperty( device, &GUID_NULL, NULL );
4111 ok( hr == DIERR_INVALIDPARAM, "GetProperty returned %#x\n", hr );
4112 hr = IDirectInputDevice8_GetProperty( device, DIPROP_VIDPID, NULL );
4113 ok( hr == DIERR_INVALIDPARAM, "GetProperty returned %#x\n", hr );
4114 hr = IDirectInputDevice8_GetProperty( device, DIPROP_VIDPID, &prop_string.diph );
4115 ok( hr == DIERR_INVALIDPARAM, "GetProperty returned %#x\n", hr );
4116 prop_dword.diph.dwHeaderSize = sizeof(DIPROPHEADER) - 1;
4117 hr = IDirectInputDevice8_GetProperty( device, DIPROP_VIDPID, &prop_dword.diph );
4118 ok( hr == DIERR_INVALIDPARAM, "GetProperty returned %#x\n", hr );
4119 prop_dword.diph.dwHeaderSize = sizeof(DIPROPHEADER);
4121 prop_dword.dwData = 0xdeadbeef;
4122 hr = IDirectInputDevice8_GetProperty( device, DIPROP_VIDPID, &prop_dword.diph );
4123 ok( hr == DI_OK, "GetProperty DIPROP_VIDPID returned %#x\n", hr );
4124 ok( prop_dword.dwData == EXPECT_VIDPID, "got %#x expected %#x\n", prop_dword.dwData, EXPECT_VIDPID );
4126 hr = IDirectInputDevice8_GetProperty( device, DIPROP_GUIDANDPATH, &prop_guid_path.diph );
4127 ok( hr == DI_OK, "GetProperty DIPROP_GUIDANDPATH returned %#x\n", hr );
4128 todo_wine
4129 ok( IsEqualGUID( &prop_guid_path.guidClass, &GUID_DEVCLASS_HIDCLASS ), "got guid %s\n",
4130 debugstr_guid( &prop_guid_path.guidClass ) );
4131 todo_wine
4132 ok( !wcsncmp( prop_guid_path.wszPath, expect_path, wcslen( expect_path ) ), "got path %s\n",
4133 debugstr_w(prop_guid_path.wszPath) );
4134 if (!(tmp = wcsrchr( prop_guid_path.wszPath, '&' )))
4135 todo_wine ok( 0, "got path %s\n", debugstr_w(prop_guid_path.wszPath) );
4136 else
4138 ok( !wcscmp( wcsrchr( prop_guid_path.wszPath, '&' ), expect_path_end ), "got path %s\n",
4139 debugstr_w(prop_guid_path.wszPath) );
4142 hr = IDirectInputDevice8_GetProperty( device, DIPROP_INSTANCENAME, &prop_string.diph );
4143 ok( hr == DI_OK, "GetProperty DIPROP_INSTANCENAME returned %#x\n", hr );
4144 todo_wine
4145 ok( !wcscmp( prop_string.wsz, expect_devinst.tszInstanceName ), "got instance %s\n",
4146 debugstr_w(prop_string.wsz) );
4147 hr = IDirectInputDevice8_GetProperty( device, DIPROP_PRODUCTNAME, &prop_string.diph );
4148 ok( hr == DI_OK, "GetProperty DIPROP_PRODUCTNAME returned %#x\n", hr );
4149 todo_wine
4150 ok( !wcscmp( prop_string.wsz, expect_devinst.tszProductName ), "got product %s\n",
4151 debugstr_w(prop_string.wsz) );
4152 hr = IDirectInputDevice8_GetProperty( device, DIPROP_TYPENAME, &prop_string.diph );
4153 todo_wine
4154 ok( hr == DI_OK, "GetProperty DIPROP_TYPENAME returned %#x\n", hr );
4155 todo_wine
4156 ok( !wcscmp( prop_string.wsz, expect_vidpid_str ), "got type %s\n", debugstr_w(prop_string.wsz) );
4157 hr = IDirectInputDevice8_GetProperty( device, DIPROP_USERNAME, &prop_string.diph );
4158 ok( hr == S_FALSE, "GetProperty DIPROP_USERNAME returned %#x\n", hr );
4159 todo_wine
4160 ok( !wcscmp( prop_string.wsz, L"" ), "got user %s\n", debugstr_w(prop_string.wsz) );
4162 prop_dword.dwData = 0xdeadbeef;
4163 hr = IDirectInputDevice8_GetProperty( device, DIPROP_JOYSTICKID, &prop_dword.diph );
4164 ok( hr == DI_OK, "GetProperty DIPROP_JOYSTICKID returned %#x\n", hr );
4165 todo_wine
4166 ok( prop_dword.dwData == 0, "got %#x expected %#x\n", prop_dword.dwData, 0 );
4168 prop_dword.dwData = 0xdeadbeef;
4169 hr = IDirectInputDevice8_GetProperty( device, DIPROP_AXISMODE, &prop_dword.diph );
4170 todo_wine
4171 ok( hr == DI_OK, "GetProperty DIPROP_AXISMODE returned %#x\n", hr );
4172 todo_wine
4173 ok( prop_dword.dwData == DIPROPAXISMODE_ABS, "got %u expected %u\n", prop_dword.dwData, DIPROPAXISMODE_ABS );
4174 prop_dword.dwData = 0xdeadbeef;
4175 hr = IDirectInputDevice8_GetProperty( device, DIPROP_BUFFERSIZE, &prop_dword.diph );
4176 ok( hr == DI_OK, "GetProperty DIPROP_BUFFERSIZE returned %#x\n", hr );
4177 ok( prop_dword.dwData == 0, "got %#x expected %#x\n", prop_dword.dwData, 0 );
4178 prop_dword.dwData = 0xdeadbeef;
4179 hr = IDirectInputDevice8_GetProperty( device, DIPROP_FFGAIN, &prop_dword.diph );
4180 ok( hr == DI_OK, "GetProperty DIPROP_FFGAIN returned %#x\n", hr );
4181 ok( prop_dword.dwData == 10000, "got %u expected %u\n", prop_dword.dwData, 10000 );
4183 hr = IDirectInputDevice8_GetProperty( device, DIPROP_CALIBRATION, &prop_dword.diph );
4184 ok( hr == DIERR_INVALIDPARAM, "GetProperty DIPROP_CALIBRATION returned %#x\n", hr );
4185 hr = IDirectInputDevice8_GetProperty( device, DIPROP_AUTOCENTER, &prop_dword.diph );
4186 ok( hr == DIERR_UNSUPPORTED, "GetProperty DIPROP_AUTOCENTER returned %#x\n", hr );
4187 hr = IDirectInputDevice8_GetProperty( device, DIPROP_DEADZONE, &prop_dword.diph );
4188 ok( hr == DIERR_UNSUPPORTED, "GetProperty DIPROP_DEADZONE returned %#x\n", hr );
4189 hr = IDirectInputDevice8_GetProperty( device, DIPROP_FFLOAD, &prop_dword.diph );
4190 ok( hr == DIERR_UNSUPPORTED, "GetProperty DIPROP_FFLOAD returned %#x\n", hr );
4191 hr = IDirectInputDevice8_GetProperty( device, DIPROP_GRANULARITY, &prop_dword.diph );
4192 ok( hr == DIERR_UNSUPPORTED, "GetProperty DIPROP_GRANULARITY returned %#x\n", hr );
4193 hr = IDirectInputDevice8_GetProperty( device, DIPROP_SATURATION, &prop_dword.diph );
4194 ok( hr == DIERR_UNSUPPORTED, "GetProperty DIPROP_SATURATION returned %#x\n", hr );
4195 hr = IDirectInputDevice8_GetProperty( device, DIPROP_CALIBRATIONMODE, &prop_dword.diph );
4196 ok( hr == DIERR_UNSUPPORTED, "GetProperty DIPROP_CALIBRATIONMODE returned %#x\n", hr );
4197 hr = IDirectInputDevice8_GetProperty( device, DIPROP_RANGE, &prop_range.diph );
4198 ok( hr == DIERR_UNSUPPORTED, "GetProperty DIPROP_RANGE returned %#x\n", hr );
4199 hr = IDirectInputDevice8_GetProperty( device, DIPROP_KEYNAME, &prop_string.diph );
4200 ok( hr == DIERR_INVALIDPARAM, "GetProperty DIPROP_KEYNAME returned %#x\n", hr );
4201 hr = IDirectInputDevice8_GetProperty( device, DIPROP_LOGICALRANGE, &prop_range.diph );
4202 ok( hr == DIERR_UNSUPPORTED, "GetProperty DIPROP_LOGICALRANGE returned %#x\n", hr );
4203 hr = IDirectInputDevice8_GetProperty( device, DIPROP_PHYSICALRANGE, &prop_range.diph );
4204 ok( hr == DIERR_UNSUPPORTED, "GetProperty DIPROP_PHYSICALRANGE returned %#x\n", hr );
4206 prop_dword.diph.dwHow = DIPH_BYUSAGE;
4207 prop_dword.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC );
4208 prop_dword.dwData = 0xdeadbeef;
4209 hr = IDirectInputDevice8_GetProperty( device, DIPROP_DEADZONE, &prop_dword.diph );
4210 ok( hr == DI_OK, "GetProperty DIPROP_DEADZONE returned %#x\n", hr );
4211 ok( prop_dword.dwData == 0, "got %u expected %u\n", prop_dword.dwData, 0 );
4212 prop_dword.dwData = 0xdeadbeef;
4213 hr = IDirectInputDevice8_GetProperty( device, DIPROP_GRANULARITY, &prop_dword.diph );
4214 ok( hr == DI_OK, "GetProperty DIPROP_GRANULARITY returned %#x\n", hr );
4215 ok( prop_dword.dwData == 1, "got %u expected %u\n", prop_dword.dwData, 1 );
4216 prop_dword.dwData = 0xdeadbeef;
4217 hr = IDirectInputDevice8_GetProperty( device, DIPROP_SATURATION, &prop_dword.diph );
4218 ok( hr == DI_OK, "GetProperty DIPROP_SATURATION returned %#x\n", hr );
4219 ok( prop_dword.dwData == 10000, "got %u expected %u\n", prop_dword.dwData, 10000 );
4220 prop_dword.dwData = 0xdeadbeef;
4221 hr = IDirectInputDevice8_GetProperty( device, DIPROP_CALIBRATIONMODE, &prop_dword.diph );
4222 ok( hr == DI_OK, "GetProperty DIPROP_CALIBRATIONMODE returned %#x\n", hr );
4223 ok( prop_dword.dwData == DIPROPCALIBRATIONMODE_COOKED, "got %u expected %u\n", prop_dword.dwData, DIPROPCALIBRATIONMODE_COOKED );
4225 prop_string.diph.dwHow = DIPH_BYUSAGE;
4226 prop_string.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC );
4227 hr = IDirectInputDevice8_GetProperty( device, DIPROP_KEYNAME, &prop_string.diph );
4228 ok( hr == DI_OK, "GetProperty DIPROP_KEYNAME returned %#x\n", hr );
4229 ok( !wcscmp( prop_string.wsz, expect_objects[4].tszName ), "got DIPROP_KEYNAME %s\n",
4230 debugstr_w( prop_string.wsz ) );
4231 prop_string.diph.dwObj = MAKELONG( 0x1, HID_USAGE_PAGE_BUTTON );
4232 hr = IDirectInputDevice8_GetProperty( device, DIPROP_KEYNAME, &prop_string.diph );
4233 todo_wine
4234 ok( hr == DIERR_NOTFOUND, "GetProperty DIPROP_KEYNAME returned %#x\n", hr );
4235 prop_string.diph.dwHow = DIPH_BYUSAGE;
4236 prop_string.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC );
4237 hr = IDirectInputDevice8_SetProperty( device, DIPROP_KEYNAME, &prop_string.diph );
4238 ok( hr == DIERR_UNSUPPORTED, "SetProperty DIPROP_KEYNAME returned %#x\n", hr );
4240 prop_range.diph.dwHow = DIPH_BYUSAGE;
4241 prop_range.diph.dwObj = MAKELONG( 0, 0 );
4242 prop_range.lMin = 0xdeadbeef;
4243 prop_range.lMax = 0xdeadbeef;
4244 hr = IDirectInputDevice8_GetProperty( device, DIPROP_RANGE, &prop_range.diph );
4245 ok( hr == DIERR_NOTFOUND, "GetProperty DIPROP_RANGE returned %#x\n", hr );
4246 prop_range.diph.dwObj = MAKELONG( 0, HID_USAGE_PAGE_GENERIC );
4247 hr = IDirectInputDevice8_GetProperty( device, DIPROP_RANGE, &prop_range.diph );
4248 ok( hr == DIERR_NOTFOUND, "GetProperty DIPROP_RANGE returned %#x\n", hr );
4249 prop_range.diph.dwObj = MAKELONG( HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_X );
4250 hr = IDirectInputDevice8_GetProperty( device, DIPROP_RANGE, &prop_range.diph );
4251 ok( hr == DIERR_NOTFOUND, "GetProperty DIPROP_RANGE returned %#x\n", hr );
4252 prop_range.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC );
4253 prop_range.lMin = 0xdeadbeef;
4254 prop_range.lMax = 0xdeadbeef;
4255 hr = IDirectInputDevice8_GetProperty( device, DIPROP_RANGE, &prop_range.diph );
4256 ok( hr == DI_OK, "GetProperty DIPROP_RANGE returned %#x\n", hr );
4257 ok( prop_range.lMin == 0, "got %d expected %d\n", prop_range.lMin, 0 );
4258 ok( prop_range.lMax == 65535, "got %d expected %d\n", prop_range.lMax, 65535 );
4259 hr = IDirectInputDevice8_GetProperty( device, DIPROP_LOGICALRANGE, &prop_range.diph );
4260 ok( hr == DI_OK, "GetProperty DIPROP_LOGICALRANGE returned %#x\n", hr );
4261 ok( prop_range.lMin == -25, "got %d expected %d\n", prop_range.lMin, -25 );
4262 ok( prop_range.lMax == 56, "got %d expected %d\n", prop_range.lMax, 56 );
4263 hr = IDirectInputDevice8_GetProperty( device, DIPROP_PHYSICALRANGE, &prop_range.diph );
4264 ok( hr == DI_OK, "GetProperty DIPROP_PHYSICALRANGE returned %#x\n", hr );
4265 ok( prop_range.lMin == -25, "got %d expected %d\n", prop_range.lMin, -25 );
4266 ok( prop_range.lMax == 56, "got %d expected %d\n", prop_range.lMax, 56 );
4268 prop_pointer.diph.dwHow = DIPH_BYUSAGE;
4269 prop_pointer.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC );
4270 hr = IDirectInputDevice8_GetProperty( device, DIPROP_APPDATA, &prop_pointer.diph );
4271 todo_wine
4272 ok( hr == DIERR_NOTINITIALIZED, "GetProperty DIPROP_APPDATA returned %#x\n", hr );
4274 hr = IDirectInputDevice8_EnumObjects( device, NULL, NULL, DIDFT_ALL );
4275 ok( hr == DIERR_INVALIDPARAM, "EnumObjects returned %#x\n", hr );
4276 hr = IDirectInputDevice8_EnumObjects( device, check_object_count, &res, 0x20 );
4277 ok( hr == DIERR_INVALIDPARAM, "EnumObjects returned %#x\n", hr );
4278 res = 0;
4279 hr = IDirectInputDevice8_EnumObjects( device, check_object_count, &res, DIDFT_AXIS | DIDFT_PSHBUTTON );
4280 ok( hr == DI_OK, "EnumObjects returned %#x\n", hr );
4281 ok( res == 8, "got %u expected %u\n", res, 8 );
4282 hr = IDirectInputDevice8_EnumObjects( device, check_objects, &check_objects_params, DIDFT_ALL );
4283 ok( hr == DI_OK, "EnumObjects returned %#x\n", hr );
4284 ok( check_objects_params.index >= check_objects_params.expect_count, "missing %u objects\n",
4285 check_objects_params.expect_count - check_objects_params.index );
4287 hr = IDirectInputDevice8_GetObjectInfo( device, NULL, 0, DIPH_DEVICE );
4288 ok( hr == E_POINTER, "GetObjectInfo returned: %#x\n", hr );
4289 hr = IDirectInputDevice8_GetObjectInfo( device, &objinst, 0, DIPH_DEVICE );
4290 ok( hr == DIERR_INVALIDPARAM, "GetObjectInfo returned: %#x\n", hr );
4291 objinst.dwSize = sizeof(DIDEVICEOBJECTINSTANCEW);
4292 hr = IDirectInputDevice8_GetObjectInfo( device, &objinst, 0, DIPH_DEVICE );
4293 ok( hr == DIERR_INVALIDPARAM, "GetObjectInfo returned: %#x\n", hr );
4295 res = MAKELONG( HID_USAGE_GENERIC_Z, HID_USAGE_PAGE_GENERIC );
4296 hr = IDirectInputDevice8_GetObjectInfo( device, &objinst, res, DIPH_BYUSAGE );
4297 ok( hr == DIERR_NOTFOUND, "GetObjectInfo returned: %#x\n", hr );
4298 res = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC );
4299 hr = IDirectInputDevice8_GetObjectInfo( device, &objinst, res, DIPH_BYUSAGE );
4300 ok( hr == DI_OK, "GetObjectInfo returned: %#x\n", hr );
4302 check_member( objinst, expect_objects[4], "%u", dwSize );
4303 check_member_guid( objinst, expect_objects[4], guidType );
4304 check_member( objinst, expect_objects[4], "%#x", dwOfs );
4305 check_member( objinst, expect_objects[4], "%#x", dwType );
4306 check_member( objinst, expect_objects[4], "%#x", dwFlags );
4307 if (!localized) check_member_wstr( objinst, expect_objects[4], tszName );
4308 check_member( objinst, expect_objects[4], "%u", dwFFMaxForce );
4309 check_member( objinst, expect_objects[4], "%u", dwFFForceResolution );
4310 check_member( objinst, expect_objects[4], "%u", wCollectionNumber );
4311 check_member( objinst, expect_objects[4], "%u", wDesignatorIndex );
4312 check_member( objinst, expect_objects[4], "%#04x", wUsagePage );
4313 check_member( objinst, expect_objects[4], "%#04x", wUsage );
4314 check_member( objinst, expect_objects[4], "%#04x", dwDimension );
4315 check_member( objinst, expect_objects[4], "%#04x", wExponent );
4316 check_member( objinst, expect_objects[4], "%u", wReportId );
4318 hr = IDirectInputDevice8_GetObjectInfo( device, &objinst, 0x14, DIPH_BYOFFSET );
4319 ok( hr == DIERR_NOTFOUND, "GetObjectInfo returned: %#x\n", hr );
4320 hr = IDirectInputDevice8_GetObjectInfo( device, &objinst, 0, DIPH_BYOFFSET );
4321 ok( hr == DIERR_NOTFOUND, "GetObjectInfo returned: %#x\n", hr );
4322 res = DIDFT_PSHBUTTON | DIDFT_MAKEINSTANCE( 3 );
4323 hr = IDirectInputDevice8_GetObjectInfo( device, &objinst, res, DIPH_BYID );
4324 ok( hr == DIERR_NOTFOUND, "GetObjectInfo returned: %#x\n", hr );
4325 res = DIDFT_PSHBUTTON | DIDFT_MAKEINSTANCE( 1 );
4326 hr = IDirectInputDevice8_GetObjectInfo( device, &objinst, res, DIPH_BYID );
4327 ok( hr == DI_OK, "GetObjectInfo returned: %#x\n", hr );
4329 check_member( objinst, expect_objects[8], "%u", dwSize );
4330 check_member_guid( objinst, expect_objects[8], guidType );
4331 check_member( objinst, expect_objects[8], "%#x", dwOfs );
4332 check_member( objinst, expect_objects[8], "%#x", dwType );
4333 check_member( objinst, expect_objects[8], "%#x", dwFlags );
4334 if (!localized) check_member_wstr( objinst, expect_objects[8], tszName );
4335 check_member( objinst, expect_objects[8], "%u", dwFFMaxForce );
4336 check_member( objinst, expect_objects[8], "%u", dwFFForceResolution );
4337 check_member( objinst, expect_objects[8], "%u", wCollectionNumber );
4338 check_member( objinst, expect_objects[8], "%u", wDesignatorIndex );
4339 check_member( objinst, expect_objects[8], "%#04x", wUsagePage );
4340 check_member( objinst, expect_objects[8], "%#04x", wUsage );
4341 check_member( objinst, expect_objects[8], "%#04x", dwDimension );
4342 check_member( objinst, expect_objects[8], "%#04x", wExponent );
4343 check_member( objinst, expect_objects[8], "%u", wReportId );
4345 hr = IDirectInputDevice8_EnumEffects( device, NULL, NULL, DIEFT_ALL );
4346 ok( hr == DIERR_INVALIDPARAM, "EnumEffects returned %#x\n", hr );
4347 res = 0;
4348 hr = IDirectInputDevice8_EnumEffects( device, check_effect_count, &res, 0xfe );
4349 ok( hr == DI_OK, "EnumEffects returned %#x\n", hr );
4350 ok( res == 0, "got %u expected %u\n", res, 0 );
4351 res = 0;
4352 hr = IDirectInputDevice8_EnumEffects( device, check_effect_count, &res, DIEFT_PERIODIC );
4353 ok( hr == DI_OK, "EnumEffects returned %#x\n", hr );
4354 ok( res == 0, "got %u expected %u\n", res, 0 );
4355 hr = IDirectInputDevice8_EnumEffects( device, check_effects, &check_effects_params, DIEFT_ALL );
4356 ok( hr == DI_OK, "EnumEffects returned %#x\n", hr );
4357 ok( check_effects_params.index >= check_effects_params.expect_count, "missing %u effects\n",
4358 check_effects_params.expect_count - check_effects_params.index );
4360 hr = IDirectInputDevice8_GetEffectInfo( device, NULL, &GUID_Sine );
4361 ok( hr == E_POINTER, "GetEffectInfo returned %#x\n", hr );
4362 effectinfo.dwSize = sizeof(DIEFFECTINFOW) + 1;
4363 hr = IDirectInputDevice8_GetEffectInfo( device, &effectinfo, &GUID_Sine );
4364 ok( hr == DIERR_INVALIDPARAM, "GetEffectInfo returned %#x\n", hr );
4365 effectinfo.dwSize = sizeof(DIEFFECTINFOW);
4366 hr = IDirectInputDevice8_GetEffectInfo( device, &effectinfo, &GUID_NULL );
4367 ok( hr == DIERR_DEVICENOTREG, "GetEffectInfo returned %#x\n", hr );
4368 hr = IDirectInputDevice8_GetEffectInfo( device, &effectinfo, &GUID_Sine );
4369 ok( hr == DIERR_DEVICENOTREG, "GetEffectInfo returned %#x\n", hr );
4371 hr = IDirectInputDevice8_SetDataFormat( device, NULL );
4372 ok( hr == E_POINTER, "SetDataFormat returned: %#x\n", hr );
4373 hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
4374 ok( hr == DIERR_INVALIDPARAM, "SetDataFormat returned: %#x\n", hr );
4375 dataformat.dwSize = sizeof(DIDATAFORMAT);
4376 hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
4377 ok( hr == DIERR_INVALIDPARAM, "SetDataFormat returned: %#x\n", hr );
4378 dataformat.dwObjSize = sizeof(DIOBJECTDATAFORMAT);
4379 hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
4380 ok( hr == DI_OK, "SetDataFormat returned: %#x\n", hr );
4381 hr = IDirectInputDevice8_SetDataFormat( device, &c_dfDIJoystick2 );
4382 ok( hr == DI_OK, "SetDataFormat returned: %#x\n", hr );
4384 hr = IDirectInputDevice8_GetObjectInfo( device, &objinst, DIJOFS_Y, DIPH_BYOFFSET );
4385 ok( hr == DI_OK, "GetObjectInfo returned: %#x\n", hr );
4387 check_member( objinst, expect_objects[3], "%u", dwSize );
4388 check_member_guid( objinst, expect_objects[3], guidType );
4389 check_member( objinst, expect_objects[3], "%#x", dwOfs );
4390 check_member( objinst, expect_objects[3], "%#x", dwType );
4391 check_member( objinst, expect_objects[3], "%#x", dwFlags );
4392 if (!localized) check_member_wstr( objinst, expect_objects[3], tszName );
4393 check_member( objinst, expect_objects[3], "%u", dwFFMaxForce );
4394 check_member( objinst, expect_objects[3], "%u", dwFFForceResolution );
4395 check_member( objinst, expect_objects[3], "%u", wCollectionNumber );
4396 check_member( objinst, expect_objects[3], "%u", wDesignatorIndex );
4397 check_member( objinst, expect_objects[3], "%#04x", wUsagePage );
4398 check_member( objinst, expect_objects[3], "%#04x", wUsage );
4399 check_member( objinst, expect_objects[3], "%#04x", dwDimension );
4400 check_member( objinst, expect_objects[3], "%#04x", wExponent );
4401 check_member( objinst, expect_objects[3], "%u", wReportId );
4403 hr = IDirectInputDevice8_SetEventNotification( device, (HANDLE)0xdeadbeef );
4404 todo_wine
4405 ok( hr == E_HANDLE, "SetEventNotification returned: %#x\n", hr );
4406 event = CreateEventW( NULL, FALSE, FALSE, NULL );
4407 ok( event != NULL, "CreateEventW failed, last error %u\n", GetLastError() );
4408 hr = IDirectInputDevice8_SetEventNotification( device, event );
4409 ok( hr == DI_OK, "SetEventNotification returned: %#x\n", hr );
4411 file = CreateFileW( prop_guid_path.wszPath, FILE_READ_ACCESS | FILE_WRITE_ACCESS,
4412 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
4413 FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING, NULL );
4414 ok( file != INVALID_HANDLE_VALUE, "got error %u\n", GetLastError() );
4416 hr = IDirectInputDevice8_SetCooperativeLevel( device, NULL, 0 );
4417 ok( hr == DIERR_INVALIDPARAM, "SetCooperativeLevel returned: %#x\n", hr );
4418 hr = IDirectInputDevice8_SetCooperativeLevel( device, NULL, DISCL_BACKGROUND );
4419 ok( hr == DIERR_INVALIDPARAM, "SetCooperativeLevel returned: %#x\n", hr );
4420 hr = IDirectInputDevice8_SetCooperativeLevel( device, NULL, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE );
4421 ok( hr == E_HANDLE, "SetCooperativeLevel returned: %#x\n", hr );
4422 hr = IDirectInputDevice8_SetCooperativeLevel( device, NULL, DISCL_BACKGROUND | DISCL_EXCLUSIVE );
4423 ok( hr == E_HANDLE, "SetCooperativeLevel returned: %#x\n", hr );
4424 hr = IDirectInputDevice8_SetCooperativeLevel( device, NULL, DISCL_FOREGROUND | DISCL_EXCLUSIVE );
4425 ok( hr == E_HANDLE, "SetCooperativeLevel returned: %#x\n", hr );
4427 hwnd = CreateWindowW( L"static", L"dinput", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 10, 10, 200, 200,
4428 NULL, NULL, NULL, NULL );
4429 SetForegroundWindow( hwnd );
4431 hr = IDirectInputDevice8_SetCooperativeLevel( device, hwnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE );
4432 ok( hr == DI_OK, "SetCooperativeLevel returned: %#x\n", hr );
4433 hr = IDirectInputDevice8_SetCooperativeLevel( device, hwnd, DISCL_BACKGROUND | DISCL_EXCLUSIVE );
4434 ok( hr == DI_OK, "SetCooperativeLevel returned: %#x\n", hr );
4435 hr = IDirectInputDevice8_SetCooperativeLevel( device, hwnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE );
4436 ok( hr == DI_OK, "SetCooperativeLevel returned: %#x\n", hr );
4438 hr = IDirectInputDevice8_Unacquire( device );
4439 ok( hr == DI_NOEFFECT, "Unacquire returned: %#x\n", hr );
4440 hr = IDirectInputDevice8_Acquire( device );
4441 ok( hr == DI_OK, "Acquire returned: %#x\n", hr );
4442 hr = IDirectInputDevice8_SetCooperativeLevel( device, hwnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE );
4443 ok( hr == DIERR_ACQUIRED, "SetCooperativeLevel returned: %#x\n", hr );
4444 hr = IDirectInputDevice8_Unacquire( device );
4445 ok( hr == DI_OK, "Unacquire returned: %#x\n", hr );
4447 DestroyWindow( hwnd );
4449 hr = IDirectInputDevice8_SetCooperativeLevel( device, NULL, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE );
4450 ok( hr == DI_OK, "SetCooperativeLevel returned: %#x\n", hr );
4452 hr = IDirectInputDevice8_GetDeviceState( device, sizeof(DIJOYSTATE2), &state );
4453 ok( hr == DIERR_NOTACQUIRED, "GetDeviceState returned: %#x\n", hr );
4455 hr = IDirectInputDevice8_Poll( device );
4456 ok( hr == DIERR_NOTACQUIRED, "Poll returned: %#x\n", hr );
4458 hr = IDirectInputDevice8_Acquire( device );
4459 ok( hr == DI_OK, "Acquire returned: %#x\n", hr );
4461 hr = IDirectInputDevice8_Poll( device );
4462 ok( hr == DI_NOEFFECT, "Poll returned: %#x\n", hr );
4464 hr = IDirectInputDevice8_GetDeviceState( device, sizeof(DIJOYSTATE2) + 1, &state );
4465 ok( hr == DIERR_INVALIDPARAM, "GetDeviceState returned: %#x\n", hr );
4467 for (i = 0; i < ARRAY_SIZE(injected_input); ++i)
4469 winetest_push_context( "state[%d]", i );
4470 hr = IDirectInputDevice8_GetDeviceState( device, sizeof(DIJOYSTATE2), &state );
4471 ok( hr == DI_OK, "GetDeviceState returned: %#x\n", hr );
4472 check_member( state, expect_state[i], "%d", lX );
4473 check_member( state, expect_state[i], "%d", lY );
4474 check_member( state, expect_state[i], "%d", lZ );
4475 check_member( state, expect_state[i], "%d", lRx );
4476 check_member( state, expect_state[i], "%#x", rgdwPOV[0] );
4477 check_member( state, expect_state[i], "%#x", rgdwPOV[1] );
4478 check_member( state, expect_state[i], "%#x", rgbButtons[0] );
4479 check_member( state, expect_state[i], "%#x", rgbButtons[1] );
4480 check_member( state, expect_state[i], "%#x", rgbButtons[2] );
4482 send_hid_input( file, &injected_input[i], sizeof(*injected_input) );
4484 res = WaitForSingleObject( event, 100 );
4485 if (i == 0 || i == 3) ok( res == WAIT_TIMEOUT, "WaitForSingleObject succeeded\n" );
4486 else ok( res == WAIT_OBJECT_0, "WaitForSingleObject failed\n" );
4487 ResetEvent( event );
4488 winetest_pop_context();
4491 hr = IDirectInputDevice8_GetDeviceState( device, sizeof(DIJOYSTATE2), &state );
4492 ok( hr == DI_OK, "GetDeviceState returned: %#x\n", hr );
4493 winetest_push_context( "state[%d]", i );
4494 check_member( state, expect_state[i], "%d", lX );
4495 check_member( state, expect_state[i], "%d", lY );
4496 check_member( state, expect_state[i], "%d", lZ );
4497 check_member( state, expect_state[i], "%d", lRx );
4498 check_member( state, expect_state[i], "%#x", rgdwPOV[0] );
4499 check_member( state, expect_state[i], "%#x", rgdwPOV[1] );
4500 check_member( state, expect_state[i], "%#x", rgbButtons[0] );
4501 check_member( state, expect_state[i], "%#x", rgbButtons[1] );
4502 check_member( state, expect_state[i], "%#x", rgbButtons[2] );
4503 winetest_pop_context();
4505 res = 1;
4506 hr = IDirectInputDevice8_GetDeviceData( device, sizeof(DIDEVICEOBJECTDATA) - 1, objdata, &res, DIGDD_PEEK );
4507 todo_wine
4508 ok( hr == DIERR_INVALIDPARAM, "GetDeviceData returned %#x\n", hr );
4509 res = 1;
4510 hr = IDirectInputDevice8_GetDeviceData( device, sizeof(DIDEVICEOBJECTDATA), objdata, &res, DIGDD_PEEK );
4511 ok( hr == DIERR_NOTBUFFERED, "GetDeviceData returned %#x\n", hr );
4513 hr = IDirectInputDevice8_Unacquire( device );
4514 ok( hr == DI_OK, "Unacquire returned: %#x\n", hr );
4515 prop_dword.diph.dwHow = DIPH_BYUSAGE;
4516 prop_dword.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC );
4517 prop_dword.dwData = 1;
4518 hr = IDirectInputDevice8_SetProperty( device, DIPROP_BUFFERSIZE, &prop_dword.diph );
4519 ok( hr == DIERR_UNSUPPORTED, "SetProperty DIPROP_BUFFERSIZE returned %#x\n", hr );
4520 prop_dword.diph.dwHow = DIPH_DEVICE;
4521 prop_dword.diph.dwObj = 0;
4522 hr = IDirectInputDevice8_SetProperty( device, DIPROP_BUFFERSIZE, &prop_dword.diph );
4523 ok( hr == DI_OK, "SetProperty DIPROP_BUFFERSIZE returned %#x\n", hr );
4524 hr = IDirectInputDevice8_Acquire( device );
4525 ok( hr == DI_OK, "Unacquire returned: %#x\n", hr );
4527 res = 1;
4528 hr = IDirectInputDevice8_GetDeviceData( device, sizeof(DIDEVICEOBJECTDATA), objdata, &res, DIGDD_PEEK );
4529 ok( hr == DI_OK, "GetDeviceData returned %#x\n", hr );
4530 ok( res == 0, "got %u expected %u\n", res, 0 );
4532 send_hid_input( file, &injected_input[0], sizeof(*injected_input) );
4533 res = WaitForSingleObject( event, 100 );
4534 ok( res == WAIT_OBJECT_0, "WaitForSingleObject failed\n" );
4535 ResetEvent( event );
4537 res = 1;
4538 hr = IDirectInputDevice8_GetDeviceData( device, sizeof(DIDEVICEOBJECTDATA), objdata, &res, DIGDD_PEEK );
4539 ok( hr == DI_BUFFEROVERFLOW, "GetDeviceData returned %#x\n", hr );
4540 ok( res == 0, "got %u expected %u\n", res, 0 );
4541 res = 1;
4542 hr = IDirectInputDevice8_GetDeviceData( device, sizeof(DIDEVICEOBJECTDATA), objdata, &res, 0 );
4543 todo_wine
4544 ok( hr == DI_OK, "GetDeviceData returned %#x\n", hr );
4545 ok( res == 0, "got %u expected %u\n", res, 0 );
4547 hr = IDirectInputDevice8_Unacquire( device );
4548 ok( hr == DI_OK, "Unacquire returned: %#x\n", hr );
4549 prop_dword.diph.dwHow = DIPH_DEVICE;
4550 prop_dword.diph.dwObj = 0;
4551 prop_dword.dwData = 10;
4552 hr = IDirectInputDevice8_SetProperty( device, DIPROP_BUFFERSIZE, &prop_dword.diph );
4553 ok( hr == DI_OK, "SetProperty DIPROP_BUFFERSIZE returned %#x\n", hr );
4554 hr = IDirectInputDevice8_Acquire( device );
4555 ok( hr == DI_OK, "Unacquire returned: %#x\n", hr );
4557 send_hid_input( file, &injected_input[1], sizeof(*injected_input) );
4558 res = WaitForSingleObject( event, 100 );
4559 ok( res == WAIT_OBJECT_0, "WaitForSingleObject failed\n" );
4560 ResetEvent( event );
4562 res = 1;
4563 hr = IDirectInputDevice8_GetDeviceData( device, sizeof(DIDEVICEOBJECTDATA), objdata, &res, DIGDD_PEEK );
4564 ok( hr == DI_OK, "GetDeviceData returned %#x\n", hr );
4565 ok( res == 1, "got %u expected %u\n", res, 1 );
4566 check_member( objdata[0], expect_objdata[0], "%#x", dwOfs );
4567 check_member( objdata[0], expect_objdata[0], "%#x", dwData );
4568 ok( objdata[0].uAppData == -1, "got %p, expected %p\n", (void *)objdata[0].uAppData, (void *)-1 );
4569 res = 4;
4570 hr = IDirectInputDevice8_GetDeviceData( device, sizeof(DIDEVICEOBJECTDATA), objdata, &res, 0 );
4571 ok( hr == DI_OK, "GetDeviceData returned %#x\n", hr );
4572 ok( res == 4, "got %u expected %u\n", res, 4 );
4573 for (i = 0; i < 4; ++i)
4575 winetest_push_context( "objdata[%d]", i );
4576 check_member( objdata[i], expect_objdata[1 + i], "%#x", dwOfs );
4577 check_member( objdata[i], expect_objdata[1 + i], "%#x", dwData );
4578 ok( objdata[i].uAppData == -1, "got %p, expected %p\n", (void *)objdata[i].uAppData, (void *)-1 );
4579 winetest_pop_context();
4582 send_hid_input( file, &injected_input[2], sizeof(*injected_input) );
4583 res = WaitForSingleObject( event, 100 );
4584 ok( res == WAIT_OBJECT_0, "WaitForSingleObject failed\n" );
4585 ResetEvent( event );
4586 send_hid_input( file, &injected_input[4], sizeof(*injected_input) );
4587 res = WaitForSingleObject( event, 100 );
4588 ok( res == WAIT_OBJECT_0, "WaitForSingleObject failed\n" );
4589 ResetEvent( event );
4591 res = 1;
4592 hr = IDirectInputDevice8_GetDeviceData( device, sizeof(DIDEVICEOBJECTDATA), objdata, &res, 0 );
4593 ok( hr == DI_BUFFEROVERFLOW, "GetDeviceData returned %#x\n", hr );
4594 ok( res == 1, "got %u expected %u\n", res, 1 );
4595 todo_wine
4596 check_member( objdata[0], expect_objdata[5], "%#x", dwOfs );
4597 todo_wine
4598 check_member( objdata[0], expect_objdata[5], "%#x", dwData );
4599 ok( objdata[0].uAppData == -1, "got %p, expected %p\n", (void *)objdata[0].uAppData, (void *)-1 );
4600 res = ARRAY_SIZE(objdata);
4601 hr = IDirectInputDevice8_GetDeviceData( device, sizeof(DIDEVICEOBJECTDATA), objdata, &res, 0 );
4602 ok( hr == DI_OK, "GetDeviceData returned %#x\n", hr );
4603 ok( res == 8, "got %u expected %u\n", res, 8 );
4604 for (i = 0; i < 8; ++i)
4606 winetest_push_context( "objdata[%d]", i );
4607 todo_wine
4608 check_member( objdata[i], expect_objdata[6 + i], "%#x", dwOfs );
4609 todo_wine_if( i == 1 || i == 2 || i == 6 )
4610 check_member( objdata[i], expect_objdata[6 + i], "%#x", dwData );
4611 ok( objdata[i].uAppData == -1, "got %p, expected %p\n", (void *)objdata[i].uAppData, (void *)-1 );
4612 winetest_pop_context();
4615 send_hid_input( file, &injected_input[3], sizeof(*injected_input) );
4616 res = WaitForSingleObject( event, 100 );
4617 ok( res == WAIT_OBJECT_0, "WaitForSingleObject failed\n" );
4618 ResetEvent( event );
4620 hr = IDirectInputDevice8_GetDeviceState( device, sizeof(DIJOYSTATE2), &state );
4621 ok( hr == DI_OK, "GetDeviceState returned: %#x\n", hr );
4622 check_member( state, expect_state[3], "%d", lX );
4623 check_member( state, expect_state[3], "%d", lY );
4624 check_member( state, expect_state[3], "%d", lZ );
4625 check_member( state, expect_state[3], "%d", lRx );
4626 check_member( state, expect_state[3], "%d", rgdwPOV[0] );
4627 check_member( state, expect_state[3], "%d", rgdwPOV[1] );
4628 check_member( state, expect_state[3], "%#x", rgbButtons[0] );
4629 check_member( state, expect_state[3], "%#x", rgbButtons[1] );
4630 check_member( state, expect_state[3], "%#x", rgbButtons[2] );
4632 hr = IDirectInputDevice8_Unacquire( device );
4633 ok( hr == DI_OK, "Unacquire returned: %#x\n", hr );
4635 dataformat.dwSize = sizeof(DIDATAFORMAT);
4636 dataformat.dwObjSize = sizeof(DIOBJECTDATAFORMAT);
4637 dataformat.dwFlags = DIDF_ABSAXIS;
4638 dataformat.dwDataSize = sizeof(buffer);
4639 dataformat.dwNumObjs = 0;
4640 dataformat.rgodf = objdataformat;
4641 hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
4642 ok( hr == DI_OK, "SetDataFormat returned: %#x\n", hr );
4644 dataformat.dwNumObjs = 1;
4645 dataformat.dwDataSize = 8;
4646 objdataformat[0].pguid = NULL;
4647 objdataformat[0].dwOfs = 2;
4648 objdataformat[0].dwType = DIDFT_AXIS|DIDFT_ANYINSTANCE;
4649 objdataformat[0].dwFlags = 0;
4650 hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
4651 todo_wine
4652 ok( hr == DIERR_INVALIDPARAM, "SetDataFormat returned: %#x\n", hr );
4653 objdataformat[0].dwOfs = 4;
4654 hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
4655 ok( hr == DI_OK, "SetDataFormat returned: %#x\n", hr );
4656 dataformat.dwDataSize = 10;
4657 hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
4658 todo_wine
4659 ok( hr == DIERR_INVALIDPARAM, "SetDataFormat returned: %#x\n", hr );
4660 dataformat.dwDataSize = 8;
4661 objdataformat[0].dwOfs = 2;
4662 objdataformat[0].dwType = DIDFT_OPTIONAL|0xff|DIDFT_ANYINSTANCE;
4663 hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
4664 todo_wine
4665 ok( hr == DIERR_INVALIDPARAM, "SetDataFormat returned: %#x\n", hr );
4667 dataformat.dwNumObjs = 2;
4668 dataformat.dwDataSize = 5;
4669 objdataformat[0].pguid = NULL;
4670 objdataformat[0].dwOfs = 4;
4671 objdataformat[0].dwType = DIDFT_BUTTON|DIDFT_ANYINSTANCE;
4672 objdataformat[0].dwFlags = 0;
4673 objdataformat[1].pguid = NULL;
4674 objdataformat[1].dwOfs = 0;
4675 objdataformat[1].dwType = DIDFT_AXIS|DIDFT_MAKEINSTANCE( 0 );
4676 objdataformat[1].dwFlags = 0;
4677 hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
4678 todo_wine
4679 ok( hr == DIERR_INVALIDPARAM, "SetDataFormat returned: %#x\n", hr );
4680 dataformat.dwDataSize = 8;
4681 hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
4682 ok( hr == DI_OK, "SetDataFormat returned: %#x\n", hr );
4684 dataformat.dwNumObjs = 4;
4685 dataformat.dwDataSize = 12;
4686 objdataformat[0].pguid = NULL;
4687 objdataformat[0].dwOfs = 0;
4688 objdataformat[0].dwType = DIDFT_AXIS|DIDFT_MAKEINSTANCE( 0 );
4689 objdataformat[0].dwFlags = 0;
4690 objdataformat[1].pguid = NULL;
4691 objdataformat[1].dwOfs = 0;
4692 objdataformat[1].dwType = DIDFT_AXIS|DIDFT_MAKEINSTANCE( 0 );
4693 objdataformat[1].dwFlags = 0;
4694 objdataformat[2].pguid = &GUID_ZAxis;
4695 objdataformat[2].dwOfs = 8;
4696 objdataformat[2].dwType = 0xff|DIDFT_ANYINSTANCE;
4697 objdataformat[2].dwFlags = 0;
4698 objdataformat[3].pguid = &GUID_POV;
4699 objdataformat[3].dwOfs = 0;
4700 objdataformat[3].dwType = 0xff|DIDFT_ANYINSTANCE;
4701 objdataformat[3].dwFlags = 0;
4702 hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
4703 ok( hr == DIERR_INVALIDPARAM, "SetDataFormat returned: %#x\n", hr );
4704 objdataformat[1].dwType = DIDFT_AXIS|DIDFT_MAKEINSTANCE( 12 );
4705 hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
4706 ok( hr == DIERR_INVALIDPARAM, "SetDataFormat returned: %#x\n", hr );
4707 objdataformat[1].dwType = DIDFT_AXIS|DIDFT_MAKEINSTANCE( 0xff );
4708 hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
4709 ok( hr == DIERR_INVALIDPARAM, "SetDataFormat returned: %#x\n", hr );
4710 objdataformat[1].dwType = DIDFT_AXIS|DIDFT_MAKEINSTANCE( 1 );
4711 hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
4712 ok( hr == DI_OK, "SetDataFormat returned: %#x\n", hr );
4713 objdataformat[1].pguid = &GUID_RzAxis;
4714 hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
4715 ok( hr == DIERR_INVALIDPARAM, "SetDataFormat returned: %#x\n", hr );
4716 objdataformat[1].pguid = &GUID_Unknown;
4717 hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
4718 ok( hr == DIERR_INVALIDPARAM, "SetDataFormat returned: %#x\n", hr );
4719 objdataformat[1].pguid = &GUID_YAxis;
4720 hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
4721 ok( hr == DI_OK, "SetDataFormat returned: %#x\n", hr );
4722 objdataformat[1].pguid = NULL;
4723 objdataformat[1].dwType = DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_MAKEINSTANCE( 0 );
4724 hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
4725 ok( hr == DI_OK, "SetDataFormat returned: %#x\n", hr );
4727 dataformat.dwNumObjs = 0;
4728 hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
4729 ok( hr == DI_OK, "SetDataFormat returned: %#x\n", hr );
4730 hr = IDirectInputDevice8_Acquire( device );
4731 ok( hr == DI_OK, "Unacquire returned: %#x\n", hr );
4733 send_hid_input( file, &injected_input[4], sizeof(*injected_input) );
4734 res = WaitForSingleObject( event, 100 );
4735 todo_wine
4736 ok( res == WAIT_TIMEOUT, "WaitForSingleObject failed\n" );
4737 ResetEvent( event );
4739 hr = IDirectInputDevice8_GetDeviceState( device, dataformat.dwDataSize, buffer );
4740 ok( hr == DI_OK, "GetDeviceState returned: %#x\n", hr );
4741 hr = IDirectInputDevice8_Unacquire( device );
4742 ok( hr == DI_OK, "Unacquire returned: %#x\n", hr );
4744 dataformat.dwNumObjs = 4;
4745 hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
4746 ok( hr == DI_OK, "SetDataFormat returned: %#x\n", hr );
4747 hr = IDirectInputDevice8_Acquire( device );
4748 ok( hr == DI_OK, "Unacquire returned: %#x\n", hr );
4750 send_hid_input( file, &injected_input[4], sizeof(*injected_input) );
4751 res = WaitForSingleObject( event, 100 );
4752 todo_wine
4753 ok( res == WAIT_OBJECT_0, "WaitForSingleObject failed\n" );
4754 ResetEvent( event );
4755 send_hid_input( file, &injected_input[3], sizeof(*injected_input) );
4756 res = WaitForSingleObject( event, 100 );
4757 ok( res == WAIT_OBJECT_0, "WaitForSingleObject failed\n" );
4758 ResetEvent( event );
4760 hr = IDirectInputDevice8_GetDeviceState( device, dataformat.dwDataSize, buffer );
4761 ok( hr == DI_OK, "GetDeviceState returned: %#x\n", hr );
4762 ok( ((ULONG *)buffer)[0] == 0x512b, "got %#x, expected %#x\n", ((ULONG *)buffer)[0], 0x512b );
4763 ok( ((ULONG *)buffer)[1] == 0, "got %#x, expected %#x\n", ((ULONG *)buffer)[1], 0 );
4764 ok( ((ULONG *)buffer)[2] == 0x7fff, "got %#x, expected %#x\n", ((ULONG *)buffer)[2], 0x7fff );
4765 hr = IDirectInputDevice8_Unacquire( device );
4766 ok( hr == DI_OK, "Unacquire returned: %#x\n", hr );
4768 hr = IDirectInputDevice8_SetDataFormat( device, &c_dfDIJoystick2 );
4769 ok( hr == DI_OK, "SetDataFormat returned: %#x\n", hr );
4770 hr = IDirectInputDevice8_Acquire( device );
4771 ok( hr == DI_OK, "Unacquire returned: %#x\n", hr );
4773 send_hid_input( file, &injected_input[4], sizeof(*injected_input) );
4774 res = WaitForSingleObject( event, 100 );
4775 ok( res == WAIT_OBJECT_0, "WaitForSingleObject failed\n" );
4776 ResetEvent( event );
4777 send_hid_input( file, &injected_input[3], sizeof(*injected_input) );
4778 res = WaitForSingleObject( event, 100 );
4779 ok( res == WAIT_OBJECT_0, "WaitForSingleObject failed\n" );
4780 ResetEvent( event );
4782 hr = IDirectInputDevice8_GetDeviceState( device, sizeof(DIJOYSTATE2), &state );
4783 ok( hr == DI_OK, "GetDeviceState returned: %#x\n", hr );
4784 check_member( state, expect_state[3], "%d", lX );
4785 check_member( state, expect_state[3], "%d", lY );
4786 check_member( state, expect_state[3], "%d", lZ );
4787 check_member( state, expect_state[3], "%d", lRx );
4788 check_member( state, expect_state[3], "%d", rgdwPOV[0] );
4789 check_member( state, expect_state[3], "%d", rgdwPOV[1] );
4790 check_member( state, expect_state[3], "%#x", rgbButtons[0] );
4791 check_member( state, expect_state[3], "%#x", rgbButtons[1] );
4792 check_member( state, expect_state[3], "%#x", rgbButtons[2] );
4794 prop_range.diph.dwHow = DIPH_DEVICE;
4795 prop_range.diph.dwObj = 0;
4796 prop_range.lMin = 1000;
4797 prop_range.lMax = 51000;
4798 hr = IDirectInputDevice8_SetProperty( device, DIPROP_RANGE, &prop_range.diph );
4799 ok( hr == DI_OK, "SetProperty DIPROP_RANGE returned %#x\n", hr );
4800 prop_range.diph.dwHow = DIPH_BYUSAGE;
4801 prop_range.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC );
4802 prop_range.lMin = -4000;
4803 prop_range.lMax = -14000;
4804 hr = IDirectInputDevice8_SetProperty( device, DIPROP_RANGE, &prop_range.diph );
4805 ok( hr == DIERR_INVALIDPARAM, "SetProperty DIPROP_RANGE returned %#x\n", hr );
4806 prop_range.lMin = -14000;
4807 prop_range.lMax = -4000;
4808 hr = IDirectInputDevice8_SetProperty( device, DIPROP_RANGE, &prop_range.diph );
4809 ok( hr == DI_OK, "SetProperty DIPROP_RANGE returned %#x\n", hr );
4810 hr = IDirectInputDevice8_SetProperty( device, DIPROP_LOGICALRANGE, &prop_range.diph );
4811 ok( hr == DIERR_ACQUIRED, "SetProperty DIPROP_LOGICALRANGE returned %#x\n", hr );
4812 hr = IDirectInputDevice8_SetProperty( device, DIPROP_PHYSICALRANGE, &prop_range.diph );
4813 ok( hr == DIERR_ACQUIRED, "SetProperty DIPROP_PHYSICALRANGE returned %#x\n", hr );
4815 hr = IDirectInputDevice8_Unacquire( device );
4816 ok( hr == DI_OK, "Unacquire returned: %#x\n", hr );
4817 hr = IDirectInputDevice8_SetProperty( device, DIPROP_LOGICALRANGE, &prop_range.diph );
4818 ok( hr == DIERR_UNSUPPORTED, "SetProperty DIPROP_LOGICALRANGE returned %#x\n", hr );
4819 hr = IDirectInputDevice8_SetProperty( device, DIPROP_PHYSICALRANGE, &prop_range.diph );
4820 ok( hr == DIERR_UNSUPPORTED, "SetProperty DIPROP_PHYSICALRANGE returned %#x\n", hr );
4821 hr = IDirectInputDevice8_Acquire( device );
4822 ok( hr == DI_OK, "Unacquire returned: %#x\n", hr );
4824 prop_range.diph.dwHow = DIPH_DEVICE;
4825 prop_range.diph.dwObj = 0;
4826 prop_range.lMin = 0xdeadbeef;
4827 prop_range.lMax = 0xdeadbeef;
4828 hr = IDirectInputDevice8_GetProperty( device, DIPROP_RANGE, &prop_range.diph );
4829 ok( hr == DIERR_UNSUPPORTED, "GetProperty DIPROP_RANGE returned %#x\n", hr );
4830 prop_range.diph.dwHow = DIPH_BYUSAGE;
4831 prop_range.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC );
4832 prop_range.lMin = 0xdeadbeef;
4833 prop_range.lMax = 0xdeadbeef;
4834 hr = IDirectInputDevice8_GetProperty( device, DIPROP_RANGE, &prop_range.diph );
4835 ok( hr == DI_OK, "GetProperty DIPROP_RANGE returned %#x\n", hr );
4836 ok( prop_range.lMin == -14000, "got %d expected %d\n", prop_range.lMin, -14000 );
4837 ok( prop_range.lMax == -4000, "got %d expected %d\n", prop_range.lMax, -4000 );
4838 prop_range.diph.dwHow = DIPH_BYUSAGE;
4839 prop_range.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_Y, HID_USAGE_PAGE_GENERIC );
4840 prop_range.lMin = 0xdeadbeef;
4841 prop_range.lMax = 0xdeadbeef;
4842 hr = IDirectInputDevice8_GetProperty( device, DIPROP_RANGE, &prop_range.diph );
4843 ok( hr == DI_OK, "GetProperty DIPROP_RANGE returned %#x\n", hr );
4844 ok( prop_range.lMin == 1000, "got %d expected %d\n", prop_range.lMin, 1000 );
4845 ok( prop_range.lMax == 51000, "got %d expected %d\n", prop_range.lMax, 51000 );
4847 hr = IDirectInputDevice8_GetDeviceState( device, sizeof(DIJOYSTATE2), &state );
4848 ok( hr == DI_OK, "GetDeviceState returned: %#x\n", hr );
4849 check_member( state, expect_state_abs[1], "%d", lX );
4850 check_member( state, expect_state_abs[1], "%d", lY );
4851 check_member( state, expect_state_abs[1], "%d", lZ );
4852 check_member( state, expect_state_abs[1], "%d", lRx );
4853 check_member( state, expect_state_abs[1], "%d", rgdwPOV[0] );
4854 check_member( state, expect_state_abs[1], "%d", rgdwPOV[1] );
4855 check_member( state, expect_state_abs[1], "%#x", rgbButtons[0] );
4856 check_member( state, expect_state_abs[1], "%#x", rgbButtons[1] );
4857 check_member( state, expect_state_abs[1], "%#x", rgbButtons[2] );
4859 hr = IDirectInputDevice8_SetProperty( device, NULL, NULL );
4860 ok( hr == DIERR_INVALIDPARAM, "SetProperty returned %#x\n", hr );
4861 hr = IDirectInputDevice8_SetProperty( device, &GUID_NULL, NULL );
4862 ok( hr == DIERR_INVALIDPARAM, "SetProperty returned %#x\n", hr );
4863 hr = IDirectInputDevice8_SetProperty( device, DIPROP_VIDPID, NULL );
4864 ok( hr == DIERR_INVALIDPARAM, "SetProperty returned %#x\n", hr );
4865 hr = IDirectInputDevice8_SetProperty( device, DIPROP_VIDPID, &prop_string.diph );
4866 ok( hr == DIERR_INVALIDPARAM, "SetProperty returned %#x\n", hr );
4868 prop_dword.diph.dwHow = DIPH_DEVICE;
4869 prop_dword.diph.dwObj = 0;
4870 prop_dword.dwData = 0xdeadbeef;
4871 hr = IDirectInputDevice8_SetProperty( device, DIPROP_VIDPID, &prop_dword.diph );
4872 ok( hr == DIERR_READONLY, "SetProperty DIPROP_VIDPID returned %#x\n", hr );
4873 hr = IDirectInputDevice8_SetProperty( device, DIPROP_GUIDANDPATH, &prop_guid_path.diph );
4874 ok( hr == DIERR_READONLY, "SetProperty DIPROP_GUIDANDPATH returned %#x\n", hr );
4876 prop_string.diph.dwHow = DIPH_DEVICE;
4877 prop_string.diph.dwObj = 0;
4878 wcscpy( prop_string.wsz, L"instance name" );
4879 hr = IDirectInputDevice8_SetProperty( device, DIPROP_INSTANCENAME, &prop_string.diph );
4880 ok( hr == DIERR_UNSUPPORTED, "SetProperty DIPROP_INSTANCENAME returned %#x\n", hr );
4882 wcscpy( prop_string.wsz, L"product name" );
4883 hr = IDirectInputDevice8_SetProperty( device, DIPROP_PRODUCTNAME, &prop_string.diph );
4884 todo_wine
4885 ok( hr == DI_OK, "SetProperty DIPROP_PRODUCTNAME returned %#x\n", hr );
4886 hr = IDirectInputDevice8_GetProperty( device, DIPROP_PRODUCTNAME, &prop_string.diph );
4887 ok( hr == DI_OK, "GetProperty DIPROP_PRODUCTNAME returned %#x\n", hr );
4888 todo_wine
4889 ok( !wcscmp( prop_string.wsz, expect_devinst.tszProductName ), "got product %s\n",
4890 debugstr_w(prop_string.wsz) );
4892 hr = IDirectInputDevice8_SetProperty( device, DIPROP_TYPENAME, &prop_string.diph );
4893 ok( hr == DIERR_READONLY, "SetProperty DIPROP_TYPENAME returned %#x\n", hr );
4894 hr = IDirectInputDevice8_SetProperty( device, DIPROP_USERNAME, &prop_string.diph );
4895 ok( hr == DIERR_READONLY, "SetProperty DIPROP_USERNAME returned %#x\n", hr );
4896 hr = IDirectInputDevice8_SetProperty( device, DIPROP_FFLOAD, &prop_dword.diph );
4897 ok( hr == DIERR_READONLY, "SetProperty DIPROP_FFLOAD returned %#x\n", hr );
4898 hr = IDirectInputDevice8_SetProperty( device, DIPROP_GRANULARITY, &prop_dword.diph );
4899 ok( hr == DIERR_READONLY, "SetProperty DIPROP_GRANULARITY returned %#x\n", hr );
4901 hr = IDirectInputDevice8_SetProperty( device, DIPROP_JOYSTICKID, &prop_dword.diph );
4902 todo_wine
4903 ok( hr == DIERR_ACQUIRED, "SetProperty DIPROP_JOYSTICKID returned %#x\n", hr );
4904 hr = IDirectInputDevice8_SetProperty( device, DIPROP_AXISMODE, &prop_dword.diph );
4905 ok( hr == DIERR_ACQUIRED, "SetProperty DIPROP_AXISMODE returned %#x\n", hr );
4906 hr = IDirectInputDevice8_SetProperty( device, DIPROP_BUFFERSIZE, &prop_dword.diph );
4907 ok( hr == DIERR_ACQUIRED, "SetProperty DIPROP_BUFFERSIZE returned %#x\n", hr );
4908 hr = IDirectInputDevice8_SetProperty( device, DIPROP_AUTOCENTER, &prop_dword.diph );
4909 ok( hr == DIERR_ACQUIRED, "SetProperty DIPROP_AUTOCENTER returned %#x\n", hr );
4910 prop_pointer.diph.dwHow = DIPH_BYUSAGE;
4911 prop_pointer.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC );
4912 hr = IDirectInputDevice8_SetProperty( device, DIPROP_APPDATA, &prop_pointer.diph );
4913 todo_wine
4914 ok( hr == DIERR_ACQUIRED, "SetProperty DIPROP_APPDATA returned %#x\n", hr );
4916 prop_dword.diph.dwHow = DIPH_DEVICE;
4917 prop_dword.diph.dwObj = 0;
4918 prop_dword.dwData = 10001;
4919 hr = IDirectInputDevice8_SetProperty( device, DIPROP_DEADZONE, &prop_dword.diph );
4920 ok( hr == DIERR_INVALIDPARAM, "SetProperty DIPROP_DEADZONE returned %#x\n", hr );
4921 hr = IDirectInputDevice8_SetProperty( device, DIPROP_SATURATION, &prop_dword.diph );
4922 ok( hr == DIERR_INVALIDPARAM, "SetProperty DIPROP_SATURATION returned %#x\n", hr );
4923 hr = IDirectInputDevice8_SetProperty( device, DIPROP_CALIBRATIONMODE, &prop_dword.diph );
4924 ok( hr == DIERR_INVALIDPARAM, "SetProperty DIPROP_CALIBRATIONMODE returned %#x\n", hr );
4925 prop_dword.dwData = 1000;
4926 hr = IDirectInputDevice8_SetProperty( device, DIPROP_DEADZONE, &prop_dword.diph );
4927 ok( hr == DI_OK, "SetProperty DIPROP_DEADZONE returned %#x\n", hr );
4928 prop_dword.dwData = 6000;
4929 hr = IDirectInputDevice8_SetProperty( device, DIPROP_SATURATION, &prop_dword.diph );
4930 ok( hr == DI_OK, "SetProperty DIPROP_SATURATION returned %#x\n", hr );
4931 prop_dword.dwData = DIPROPCALIBRATIONMODE_COOKED;
4932 hr = IDirectInputDevice8_SetProperty( device, DIPROP_CALIBRATIONMODE, &prop_dword.diph );
4933 ok( hr == DI_OK, "SetProperty DIPROP_CALIBRATIONMODE returned %#x\n", hr );
4935 hr = IDirectInputDevice8_GetProperty( device, DIPROP_DEADZONE, &prop_dword.diph );
4936 ok( hr == DIERR_UNSUPPORTED, "GetProperty DIPROP_DEADZONE returned %#x\n", hr );
4937 hr = IDirectInputDevice8_GetProperty( device, DIPROP_SATURATION, &prop_dword.diph );
4938 ok( hr == DIERR_UNSUPPORTED, "GetProperty DIPROP_SATURATION returned %#x\n", hr );
4939 hr = IDirectInputDevice8_GetProperty( device, DIPROP_CALIBRATIONMODE, &prop_dword.diph );
4940 ok( hr == DIERR_UNSUPPORTED, "GetProperty DIPROP_CALIBRATIONMODE returned %#x\n", hr );
4942 prop_dword.diph.dwHow = DIPH_BYUSAGE;
4943 prop_dword.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC );
4944 prop_dword.dwData = 2000;
4945 hr = IDirectInputDevice8_SetProperty( device, DIPROP_DEADZONE, &prop_dword.diph );
4946 ok( hr == DI_OK, "SetProperty DIPROP_DEADZONE returned %#x\n", hr );
4947 ok( prop_dword.dwData == 2000, "got %u expected %u\n", prop_dword.dwData, 2000 );
4948 prop_dword.dwData = 7000;
4949 hr = IDirectInputDevice8_SetProperty( device, DIPROP_SATURATION, &prop_dword.diph );
4950 ok( hr == DI_OK, "SetProperty DIPROP_SATURATION returned %#x\n", hr );
4952 prop_dword.diph.dwHow = DIPH_BYUSAGE;
4953 prop_dword.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC );
4954 prop_dword.dwData = 0xdeadbeef;
4955 hr = IDirectInputDevice8_GetProperty( device, DIPROP_DEADZONE, &prop_dword.diph );
4956 ok( hr == DI_OK, "GetProperty DIPROP_DEADZONE returned %#x\n", hr );
4957 ok( prop_dword.dwData == 2000, "got %u expected %u\n", prop_dword.dwData, 2000 );
4958 prop_dword.dwData = 0xdeadbeef;
4959 hr = IDirectInputDevice8_GetProperty( device, DIPROP_SATURATION, &prop_dword.diph );
4960 ok( hr == DI_OK, "GetProperty DIPROP_SATURATION returned %#x\n", hr );
4961 ok( prop_dword.dwData == 7000, "got %u expected %u\n", prop_dword.dwData, 7000 );
4963 prop_dword.diph.dwHow = DIPH_BYUSAGE;
4964 prop_dword.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_Y, HID_USAGE_PAGE_GENERIC );
4965 prop_dword.dwData = 0xdeadbeef;
4966 hr = IDirectInputDevice8_GetProperty( device, DIPROP_DEADZONE, &prop_dword.diph );
4967 ok( hr == DI_OK, "GetProperty DIPROP_DEADZONE returned %#x\n", hr );
4968 ok( prop_dword.dwData == 1000, "got %u expected %u\n", prop_dword.dwData, 1000 );
4969 prop_dword.dwData = 0xdeadbeef;
4970 hr = IDirectInputDevice8_GetProperty( device, DIPROP_SATURATION, &prop_dword.diph );
4971 ok( hr == DI_OK, "GetProperty DIPROP_SATURATION returned %#x\n", hr );
4972 ok( prop_dword.dwData == 6000, "got %u expected %u\n", prop_dword.dwData, 6000 );
4974 for (i = 0; i < ARRAY_SIZE(injected_input); ++i)
4976 winetest_push_context( "state[%d]", i );
4977 hr = IDirectInputDevice8_GetDeviceState( device, sizeof(DIJOYSTATE2), &state );
4978 ok( hr == DI_OK, "GetDeviceState returned: %#x\n", hr );
4979 if (broken( state.lX == -10750 )) win_skip( "Ignoring 32-bit rounding\n" );
4980 else
4982 check_member( state, expect_state_abs[i], "%d", lX );
4983 check_member( state, expect_state_abs[i], "%d", lY );
4985 check_member( state, expect_state_abs[i], "%d", lZ );
4986 check_member( state, expect_state_abs[i], "%d", lRx );
4987 check_member( state, expect_state_abs[i], "%d", rgdwPOV[0] );
4988 check_member( state, expect_state_abs[i], "%d", rgdwPOV[1] );
4989 check_member( state, expect_state_abs[i], "%#x", rgbButtons[0] );
4990 check_member( state, expect_state_abs[i], "%#x", rgbButtons[1] );
4991 check_member( state, expect_state_abs[i], "%#x", rgbButtons[2] );
4993 send_hid_input( file, &injected_input[i], sizeof(*injected_input) );
4995 res = WaitForSingleObject( event, 100 );
4996 if (i == 0 || i == 3) ok( res == WAIT_TIMEOUT, "WaitForSingleObject succeeded\n" );
4997 else ok( res == WAIT_OBJECT_0, "WaitForSingleObject failed\n" );
4998 ResetEvent( event );
4999 winetest_pop_context();
5002 hr = IDirectInputDevice8_GetDeviceState( device, sizeof(DIJOYSTATE2), &state );
5003 ok( hr == DI_OK, "GetDeviceState returned: %#x\n", hr );
5004 winetest_push_context( "state[%d]", i );
5005 check_member( state, expect_state_abs[i], "%d", lX );
5006 check_member( state, expect_state_abs[i], "%d", lY );
5007 check_member( state, expect_state_abs[i], "%d", lZ );
5008 check_member( state, expect_state_abs[i], "%d", lRx );
5009 check_member( state, expect_state_abs[i], "%d", rgdwPOV[0] );
5010 check_member( state, expect_state_abs[i], "%d", rgdwPOV[1] );
5011 check_member( state, expect_state_abs[i], "%#x", rgbButtons[0] );
5012 check_member( state, expect_state_abs[i], "%#x", rgbButtons[1] );
5013 check_member( state, expect_state_abs[i], "%#x", rgbButtons[2] );
5014 winetest_pop_context();
5016 prop_dword.diph.dwHow = DIPH_BYUSAGE;
5017 prop_dword.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC );
5018 prop_dword.dwData = DIPROPCALIBRATIONMODE_RAW;
5019 hr = IDirectInputDevice8_SetProperty( device, DIPROP_CALIBRATIONMODE, &prop_dword.diph );
5020 ok( hr == DI_OK, "SetProperty DIPROP_CALIBRATIONMODE returned %#x\n", hr );
5021 prop_dword.dwData = 0xdeadbeef;
5022 hr = IDirectInputDevice8_GetProperty( device, DIPROP_CALIBRATIONMODE, &prop_dword.diph );
5023 ok( hr == DI_OK, "GetProperty DIPROP_CALIBRATIONMODE returned %#x\n", hr );
5024 ok( prop_dword.dwData == DIPROPCALIBRATIONMODE_RAW, "got %u expected %u\n", prop_dword.dwData, DIPROPCALIBRATIONMODE_RAW );
5026 hr = IDirectInputDevice8_GetDeviceState( device, sizeof(DIJOYSTATE2), &state );
5027 ok( hr == DI_OK, "GetDeviceState returned: %#x\n", hr );
5028 winetest_push_context( "state[%d]", i );
5029 todo_wine
5030 ok( state.lX == 15, "got lX %d, expected %d\n" , state.lX, 15 );
5031 check_member( state, expect_state_abs[0], "%d", lY );
5032 check_member( state, expect_state_abs[0], "%d", lZ );
5033 check_member( state, expect_state_abs[0], "%d", lRx );
5034 check_member( state, expect_state_abs[0], "%d", rgdwPOV[0] );
5035 check_member( state, expect_state_abs[0], "%d", rgdwPOV[1] );
5036 winetest_pop_context();
5038 prop_dword.dwData = DIPROPCALIBRATIONMODE_COOKED;
5039 hr = IDirectInputDevice8_SetProperty( device, DIPROP_CALIBRATIONMODE, &prop_dword.diph );
5040 ok( hr == DI_OK, "SetProperty DIPROP_CALIBRATIONMODE returned %#x\n", hr );
5042 send_hid_input( file, &injected_input[ARRAY_SIZE(injected_input) - 1], sizeof(*injected_input) );
5043 res = WaitForSingleObject( event, 100 );
5044 ok( res == WAIT_OBJECT_0, "WaitForSingleObject failed\n" );
5046 hr = IDirectInputDevice8_Unacquire( device );
5047 ok( hr == DI_OK, "Unacquire returned: %#x\n", hr );
5049 prop_dword.diph.dwHow = DIPH_DEVICE;
5050 prop_dword.diph.dwObj = 0;
5051 hr = IDirectInputDevice8_SetProperty( device, DIPROP_JOYSTICKID, &prop_dword.diph );
5052 ok( hr == DIERR_UNSUPPORTED, "SetProperty DIPROP_JOYSTICKID returned %#x\n", hr );
5053 prop_dword.dwData = 0x1000;
5054 hr = IDirectInputDevice8_SetProperty( device, DIPROP_BUFFERSIZE, &prop_dword.diph );
5055 ok( hr == DI_OK, "SetProperty DIPROP_BUFFERSIZE returned %#x\n", hr );
5056 prop_dword.dwData = 0xdeadbeef;
5057 hr = IDirectInputDevice8_SetProperty( device, DIPROP_AUTOCENTER, &prop_dword.diph );
5058 ok( hr == DIERR_INVALIDPARAM, "SetProperty DIPROP_AUTOCENTER returned %#x\n", hr );
5059 prop_dword.dwData = DIPROPAUTOCENTER_ON;
5060 hr = IDirectInputDevice8_SetProperty( device, DIPROP_AUTOCENTER, &prop_dword.diph );
5061 ok( hr == DIERR_UNSUPPORTED, "SetProperty DIPROP_AUTOCENTER returned %#x\n", hr );
5062 prop_pointer.diph.dwHow = DIPH_BYUSAGE;
5063 prop_pointer.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC );
5064 prop_pointer.uData = 0xfeedcafe;
5065 hr = IDirectInputDevice8_SetProperty( device, DIPROP_APPDATA, &prop_pointer.diph );
5066 ok( hr == DI_OK, "SetProperty DIPROP_APPDATA returned %#x\n", hr );
5068 prop_dword.dwData = 0xdeadbeef;
5069 hr = IDirectInputDevice8_SetProperty( device, DIPROP_AXISMODE, &prop_dword.diph );
5070 ok( hr == DIERR_INVALIDPARAM, "SetProperty DIPROP_AXISMODE returned %#x\n", hr );
5071 prop_dword.dwData = DIPROPAXISMODE_REL;
5072 hr = IDirectInputDevice8_SetProperty( device, DIPROP_AXISMODE, &prop_dword.diph );
5073 ok( hr == DI_OK, "SetProperty DIPROP_AXISMODE returned %#x\n", hr );
5075 hr = IDirectInputDevice8_Acquire( device );
5076 ok( hr == DI_OK, "Unacquire returned: %#x\n", hr );
5078 prop_dword.dwData = 0xdeadbeef;
5079 hr = IDirectInputDevice8_GetProperty( device, DIPROP_AXISMODE, &prop_dword.diph );
5080 todo_wine
5081 ok( hr == DI_OK, "GetProperty DIPROP_AXISMODE returned %#x\n", hr );
5082 todo_wine
5083 ok( prop_dword.dwData == DIPROPAXISMODE_REL, "got %u expected %u\n", prop_dword.dwData, DIPROPAXISMODE_REL );
5085 prop_dword.dwData = 0xdeadbeef;
5086 hr = IDirectInputDevice8_GetProperty( device, DIPROP_BUFFERSIZE, &prop_dword.diph );
5087 ok( hr == DI_OK, "GetProperty DIPROP_BUFFERSIZE returned %#x\n", hr );
5088 ok( prop_dword.dwData == 0x1000, "got %#x expected %#x\n", prop_dword.dwData, 0x1000 );
5090 prop_pointer.diph.dwHow = DIPH_BYUSAGE;
5091 prop_pointer.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC );
5092 hr = IDirectInputDevice8_GetProperty( device, DIPROP_APPDATA, &prop_pointer.diph );
5093 todo_wine
5094 ok( hr == DI_OK, "GetProperty DIPROP_APPDATA returned %#x\n", hr );
5095 ok( prop_pointer.uData == 0xfeedcafe, "got %p expected %p\n", (void *)prop_pointer.uData, (void *)0xfeedcafe );
5097 prop_dword.diph.dwHow = DIPH_DEVICE;
5098 prop_dword.diph.dwObj = 0;
5099 prop_dword.dwData = 0xdeadbeef;
5100 hr = IDirectInputDevice8_SetProperty( device, DIPROP_FFGAIN, &prop_dword.diph );
5101 ok( hr == DIERR_INVALIDPARAM, "SetProperty DIPROP_FFGAIN returned %#x\n", hr );
5102 prop_dword.dwData = 1000;
5103 hr = IDirectInputDevice8_SetProperty( device, DIPROP_FFGAIN, &prop_dword.diph );
5104 ok( hr == DI_OK, "SetProperty DIPROP_FFGAIN returned %#x\n", hr );
5106 prop_dword.dwData = 0xdeadbeef;
5107 hr = IDirectInputDevice8_SetProperty( device, DIPROP_CALIBRATION, &prop_dword.diph );
5108 todo_wine
5109 ok( hr == DIERR_INVALIDPARAM, "SetProperty DIPROP_CALIBRATION returned %#x\n", hr );
5110 prop_dword.dwData = 0xdeadbeef;
5111 hr = IDirectInputDevice8_SetProperty( device, DIPROP_DEADZONE, &prop_dword.diph );
5112 ok( hr == DIERR_INVALIDPARAM, "SetProperty DIPROP_DEADZONE returned %#x\n", hr );
5113 prop_dword.dwData = 0xdeadbeef;
5114 hr = IDirectInputDevice8_SetProperty( device, DIPROP_SATURATION, &prop_dword.diph );
5115 ok( hr == DIERR_INVALIDPARAM, "SetProperty DIPROP_SATURATION returned %#x\n", hr );
5117 for (i = 0; i < ARRAY_SIZE(injected_input); ++i)
5119 winetest_push_context( "state[%d]", i );
5120 hr = IDirectInputDevice8_GetDeviceState( device, sizeof(DIJOYSTATE2), &state );
5121 ok( hr == DI_OK, "GetDeviceState returned: %#x\n", hr );
5122 todo_wine
5123 check_member( state, expect_state_rel[i], "%d", lX );
5124 todo_wine
5125 check_member( state, expect_state_rel[i], "%d", lY );
5126 todo_wine
5127 check_member( state, expect_state_rel[i], "%d", lZ );
5128 check_member( state, expect_state_rel[i], "%d", lRx );
5129 check_member( state, expect_state_rel[i], "%d", rgdwPOV[0] );
5130 check_member( state, expect_state_rel[i], "%d", rgdwPOV[1] );
5131 check_member( state, expect_state_rel[i], "%#x", rgbButtons[0] );
5132 check_member( state, expect_state_rel[i], "%#x", rgbButtons[1] );
5133 check_member( state, expect_state_rel[i], "%#x", rgbButtons[2] );
5135 send_hid_input( file, &injected_input[i], sizeof(*injected_input) );
5137 res = WaitForSingleObject( event, 100 );
5138 if (i == 3) ok( res == WAIT_TIMEOUT, "WaitForSingleObject succeeded\n" );
5139 else ok( res == WAIT_OBJECT_0, "WaitForSingleObject failed\n" );
5140 ResetEvent( event );
5141 winetest_pop_context();
5144 hr = IDirectInputDevice8_GetDeviceState( device, sizeof(DIJOYSTATE2), &state );
5145 ok( hr == DI_OK, "GetDeviceState returned: %#x\n", hr );
5146 winetest_push_context( "state[%d]", i );
5147 todo_wine
5148 check_member( state, expect_state_rel[i], "%d", lX );
5149 todo_wine
5150 check_member( state, expect_state_rel[i], "%d", lY );
5151 todo_wine
5152 check_member( state, expect_state_rel[i], "%d", lZ );
5153 check_member( state, expect_state_rel[i], "%d", lRx );
5154 check_member( state, expect_state_rel[i], "%d", rgdwPOV[0] );
5155 check_member( state, expect_state_rel[i], "%d", rgdwPOV[1] );
5156 check_member( state, expect_state_rel[i], "%#x", rgbButtons[0] );
5157 check_member( state, expect_state_rel[i], "%#x", rgbButtons[1] );
5158 check_member( state, expect_state_rel[i], "%#x", rgbButtons[2] );
5159 winetest_pop_context();
5161 hr = IDirectInputDevice8_GetForceFeedbackState( device, NULL );
5162 ok( hr == E_POINTER, "GetForceFeedbackState returned %#x\n", hr );
5163 res = 0xdeadbeef;
5164 hr = IDirectInputDevice8_GetForceFeedbackState( device, &res );
5165 ok( hr == DIERR_UNSUPPORTED, "GetForceFeedbackState returned %#x\n", hr );
5167 hr = IDirectInputDevice8_SendForceFeedbackCommand( device, 0xdeadbeef );
5168 ok( hr == DIERR_INVALIDPARAM, "SendForceFeedbackCommand returned %#x\n", hr );
5169 hr = IDirectInputDevice8_SendForceFeedbackCommand( device, DISFFC_RESET );
5170 ok( hr == DIERR_UNSUPPORTED, "SendForceFeedbackCommand returned %#x\n", hr );
5172 objdata[0].dwOfs = 0xd;
5173 objdata[0].dwData = 0x80;
5174 res = 1;
5175 hr = IDirectInputDevice8_SendDeviceData( device, sizeof(DIDEVICEOBJECTDATA), objdata, &res, 0xdeadbeef );
5176 todo_wine
5177 ok( hr == DIERR_INVALIDPARAM, "SendDeviceData returned %#x\n", hr );
5178 res = 1;
5179 hr = IDirectInputDevice8_SendDeviceData( device, sizeof(DIDEVICEOBJECTDATA), objdata, &res, 1 /*DISDD_CONTINUE*/ );
5180 todo_wine
5181 ok( hr == DIERR_INVALIDPARAM, "SendDeviceData returned %#x\n", hr );
5182 res = 1;
5183 hr = IDirectInputDevice8_SendDeviceData( device, sizeof(DIDEVICEOBJECTDATA), objdata, &res, 0 );
5184 todo_wine
5185 ok( hr == DIERR_INVALIDPARAM, "SendDeviceData returned %#x\n", hr );
5187 hr = IDirectInputDevice8_CreateEffect( device, &GUID_Sine, NULL, NULL, NULL );
5188 ok( hr == E_POINTER, "CreateEffect returned %#x\n", hr );
5189 hr = IDirectInputDevice8_CreateEffect( device, NULL, NULL, &effect, NULL );
5190 ok( hr == DIERR_UNSUPPORTED, "CreateEffect returned %#x\n", hr );
5191 hr = IDirectInputDevice8_CreateEffect( device, &GUID_NULL, NULL, &effect, NULL );
5192 ok( hr == DIERR_UNSUPPORTED, "CreateEffect returned %#x\n", hr );
5193 hr = IDirectInputDevice8_CreateEffect( device, &GUID_Sine, NULL, &effect, NULL );
5194 ok( hr == DIERR_UNSUPPORTED, "CreateEffect returned %#x\n", hr );
5196 hr = IDirectInputDevice8_Unacquire( device );
5197 ok( hr == DI_OK, "Unacquire returned: %#x\n", hr );
5199 hr = IDirectInputDevice8_CreateEffect( device, &GUID_Sine, NULL, &effect, NULL );
5200 ok( hr == DIERR_UNSUPPORTED, "CreateEffect returned %#x\n", hr );
5202 hr = IDirectInputDevice8_EnumCreatedEffectObjects( device, NULL, effect, 0 );
5203 ok( hr == DIERR_INVALIDPARAM, "EnumCreatedEffectObjects returned %#x\n", hr );
5204 hr = IDirectInputDevice8_EnumCreatedEffectObjects( device, check_no_created_effect_objects, effect, 0xdeadbeef );
5205 ok( hr == DIERR_INVALIDPARAM, "EnumCreatedEffectObjects returned %#x\n", hr );
5206 hr = IDirectInputDevice8_EnumCreatedEffectObjects( device, check_no_created_effect_objects, (void *)0xdeadbeef, 0 );
5207 ok( hr == DI_OK, "EnumCreatedEffectObjects returned %#x\n", hr );
5209 hr = IDirectInputDevice8_Escape( device, NULL );
5210 todo_wine
5211 ok( hr == E_POINTER, "Escape returned: %#x\n", hr );
5212 hr = IDirectInputDevice8_Escape( device, &escape );
5213 todo_wine
5214 ok( hr == DIERR_INVALIDPARAM, "Escape returned: %#x\n", hr );
5215 escape.dwSize = sizeof(DIEFFESCAPE) + 1;
5216 hr = IDirectInputDevice8_Escape( device, &escape );
5217 todo_wine
5218 ok( hr == DIERR_INVALIDPARAM, "Escape returned: %#x\n", hr );
5219 escape.dwSize = sizeof(DIEFFESCAPE);
5220 escape.dwCommand = 0;
5221 escape.lpvInBuffer = buffer;
5222 escape.cbInBuffer = 10;
5223 escape.lpvOutBuffer = buffer + 10;
5224 escape.cbOutBuffer = 10;
5225 hr = IDirectInputDevice8_Escape( device, &escape );
5226 todo_wine
5227 ok( hr == DIERR_UNSUPPORTED, "Escape returned: %#x\n", hr );
5229 ref = IDirectInputDevice8_Release( device );
5230 ok( ref == 0, "Release returned %d\n", ref );
5232 CloseHandle( event );
5233 CloseHandle( file );
5235 done:
5236 pnp_driver_stop();
5237 cleanup_registry_keys();
5238 SetCurrentDirectoryW( cwd );
5241 struct device_desc
5243 const BYTE *report_desc_buf;
5244 ULONG report_desc_len;
5245 HIDP_CAPS hid_caps;
5248 static BOOL test_device_types( DWORD version )
5250 #include "psh_hid_macros.h"
5251 static const unsigned char unknown_desc[] =
5253 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
5254 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
5255 COLLECTION(1, Application),
5256 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
5257 COLLECTION(1, Physical),
5258 USAGE_PAGE(1, HID_USAGE_PAGE_BUTTON),
5259 USAGE_MINIMUM(1, 1),
5260 USAGE_MAXIMUM(1, 6),
5261 LOGICAL_MINIMUM(1, 0),
5262 LOGICAL_MAXIMUM(1, 1),
5263 PHYSICAL_MINIMUM(1, 0),
5264 PHYSICAL_MAXIMUM(1, 1),
5265 REPORT_SIZE(1, 1),
5266 REPORT_COUNT(1, 8),
5267 INPUT(1, Data|Var|Abs),
5268 END_COLLECTION,
5269 END_COLLECTION,
5271 static const unsigned char limited_desc[] =
5273 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
5274 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
5275 COLLECTION(1, Application),
5276 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
5277 COLLECTION(1, Physical),
5278 USAGE(1, HID_USAGE_GENERIC_X),
5279 USAGE(1, HID_USAGE_GENERIC_Y),
5280 LOGICAL_MINIMUM(1, 0),
5281 LOGICAL_MAXIMUM(1, 127),
5282 PHYSICAL_MINIMUM(1, 0),
5283 PHYSICAL_MAXIMUM(1, 127),
5284 REPORT_SIZE(1, 8),
5285 REPORT_COUNT(1, 2),
5286 INPUT(1, Data|Var|Abs),
5288 USAGE_PAGE(1, HID_USAGE_PAGE_BUTTON),
5289 USAGE_MINIMUM(1, 1),
5290 USAGE_MAXIMUM(1, 6),
5291 LOGICAL_MINIMUM(1, 0),
5292 LOGICAL_MAXIMUM(1, 1),
5293 PHYSICAL_MINIMUM(1, 0),
5294 PHYSICAL_MAXIMUM(1, 1),
5295 REPORT_SIZE(1, 1),
5296 REPORT_COUNT(1, 8),
5297 INPUT(1, Data|Var|Abs),
5298 END_COLLECTION,
5299 END_COLLECTION,
5301 static const unsigned char gamepad_desc[] =
5303 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
5304 USAGE(1, HID_USAGE_GENERIC_GAMEPAD),
5305 COLLECTION(1, Application),
5306 USAGE(1, HID_USAGE_GENERIC_GAMEPAD),
5307 COLLECTION(1, Physical),
5308 USAGE(1, HID_USAGE_GENERIC_X),
5309 USAGE(1, HID_USAGE_GENERIC_Y),
5310 LOGICAL_MINIMUM(1, 0),
5311 LOGICAL_MAXIMUM(1, 127),
5312 PHYSICAL_MINIMUM(1, 0),
5313 PHYSICAL_MAXIMUM(1, 127),
5314 REPORT_SIZE(1, 8),
5315 REPORT_COUNT(1, 2),
5316 INPUT(1, Data|Var|Abs),
5318 USAGE_PAGE(1, HID_USAGE_PAGE_BUTTON),
5319 USAGE_MINIMUM(1, 1),
5320 USAGE_MAXIMUM(1, 6),
5321 LOGICAL_MINIMUM(1, 0),
5322 LOGICAL_MAXIMUM(1, 1),
5323 PHYSICAL_MINIMUM(1, 0),
5324 PHYSICAL_MAXIMUM(1, 1),
5325 REPORT_SIZE(1, 1),
5326 REPORT_COUNT(1, 8),
5327 INPUT(1, Data|Var|Abs),
5328 END_COLLECTION,
5329 END_COLLECTION,
5331 static const unsigned char joystick_desc[] =
5333 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
5334 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
5335 COLLECTION(1, Application),
5336 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
5337 COLLECTION(1, Physical),
5338 USAGE(1, HID_USAGE_GENERIC_X),
5339 USAGE(1, HID_USAGE_GENERIC_Y),
5340 USAGE(1, HID_USAGE_GENERIC_Z),
5341 LOGICAL_MINIMUM(1, 0),
5342 LOGICAL_MAXIMUM(1, 127),
5343 PHYSICAL_MINIMUM(1, 0),
5344 PHYSICAL_MAXIMUM(1, 127),
5345 REPORT_SIZE(1, 8),
5346 REPORT_COUNT(1, 3),
5347 INPUT(1, Data|Var|Abs),
5349 USAGE(1, HID_USAGE_GENERIC_HATSWITCH),
5350 LOGICAL_MINIMUM(1, 1),
5351 LOGICAL_MAXIMUM(1, 8),
5352 PHYSICAL_MINIMUM(1, 0),
5353 PHYSICAL_MAXIMUM(1, 8),
5354 REPORT_SIZE(1, 8),
5355 REPORT_COUNT(1, 1),
5356 INPUT(1, Data|Var|Abs|Null),
5358 USAGE_PAGE(1, HID_USAGE_PAGE_BUTTON),
5359 USAGE_MINIMUM(1, 1),
5360 USAGE_MAXIMUM(1, 5),
5361 LOGICAL_MINIMUM(1, 0),
5362 LOGICAL_MAXIMUM(1, 1),
5363 PHYSICAL_MINIMUM(1, 0),
5364 PHYSICAL_MAXIMUM(1, 1),
5365 REPORT_SIZE(1, 1),
5366 REPORT_COUNT(1, 8),
5367 INPUT(1, Data|Var|Abs),
5368 END_COLLECTION,
5369 END_COLLECTION,
5371 #include "pop_hid_macros.h"
5373 static struct device_desc device_desc[] =
5376 .report_desc_buf = unknown_desc,
5377 .report_desc_len = sizeof(unknown_desc),
5378 .hid_caps =
5380 .InputReportByteLength = 1,
5384 .report_desc_buf = limited_desc,
5385 .report_desc_len = sizeof(limited_desc),
5386 .hid_caps =
5388 .InputReportByteLength = 3,
5392 .report_desc_buf = gamepad_desc,
5393 .report_desc_len = sizeof(gamepad_desc),
5394 .hid_caps =
5396 .InputReportByteLength = 3,
5400 .report_desc_buf = joystick_desc,
5401 .report_desc_len = sizeof(joystick_desc),
5402 .hid_caps =
5404 .InputReportByteLength = 5,
5408 const DIDEVCAPS expect_caps[] =
5411 .dwSize = sizeof(DIDEVCAPS),
5412 .dwFlags = DIDC_ATTACHED|DIDC_EMULATED,
5413 .dwDevType = version >= 0x800 ? DIDEVTYPE_HID|(DI8DEVTYPESUPPLEMENTAL_UNKNOWN << 8)|DI8DEVTYPE_SUPPLEMENTAL
5414 : DIDEVTYPE_HID|(DIDEVTYPEJOYSTICK_UNKNOWN << 8)|DIDEVTYPE_JOYSTICK,
5415 .dwButtons = 6,
5418 .dwSize = sizeof(DIDEVCAPS),
5419 .dwFlags = DIDC_ATTACHED|DIDC_EMULATED,
5420 .dwDevType = version >= 0x800 ? DIDEVTYPE_HID|(DI8DEVTYPEJOYSTICK_LIMITED << 8)|DI8DEVTYPE_JOYSTICK
5421 : DIDEVTYPE_HID|(DIDEVTYPEJOYSTICK_UNKNOWN << 8)|DIDEVTYPE_JOYSTICK,
5422 .dwAxes = 2,
5423 .dwButtons = 6,
5426 .dwSize = sizeof(DIDEVCAPS),
5427 .dwFlags = DIDC_ATTACHED|DIDC_EMULATED,
5428 .dwDevType = version >= 0x800 ? DIDEVTYPE_HID|(DI8DEVTYPEGAMEPAD_STANDARD << 8)|DI8DEVTYPE_GAMEPAD
5429 : DIDEVTYPE_HID|(DIDEVTYPEJOYSTICK_GAMEPAD << 8)|DIDEVTYPE_JOYSTICK,
5430 .dwAxes = 2,
5431 .dwButtons = 6,
5434 .dwSize = sizeof(DIDEVCAPS),
5435 .dwFlags = DIDC_ATTACHED|DIDC_EMULATED,
5436 .dwDevType = version >= 0x800 ? DIDEVTYPE_HID|(DI8DEVTYPEJOYSTICK_STANDARD << 8)|DI8DEVTYPE_JOYSTICK
5437 : DIDEVTYPE_HID|(DIDEVTYPEJOYSTICK_UNKNOWN << 8)|DIDEVTYPE_JOYSTICK,
5438 .dwAxes = 3,
5439 .dwPOVs = 1,
5440 .dwButtons = 5,
5444 const DIDEVICEINSTANCEW expect_devinst[] =
5447 .dwSize = sizeof(DIDEVICEINSTANCEW),
5448 .guidInstance = expect_guid_product,
5449 .guidProduct = expect_guid_product,
5450 .dwDevType = version >= 0x800 ? DIDEVTYPE_HID|(DI8DEVTYPESUPPLEMENTAL_UNKNOWN << 8)|DI8DEVTYPE_SUPPLEMENTAL
5451 : DIDEVTYPE_HID|(DIDEVTYPEJOYSTICK_UNKNOWN << 8)|DIDEVTYPE_JOYSTICK,
5452 .tszInstanceName = L"Wine test root driver",
5453 .tszProductName = L"Wine test root driver",
5454 .guidFFDriver = GUID_NULL,
5455 .wUsagePage = HID_USAGE_PAGE_GENERIC,
5456 .wUsage = HID_USAGE_GENERIC_JOYSTICK,
5459 .dwSize = sizeof(DIDEVICEINSTANCEW),
5460 .guidInstance = expect_guid_product,
5461 .guidProduct = expect_guid_product,
5462 .dwDevType = version >= 0x800 ? DIDEVTYPE_HID|(DI8DEVTYPEJOYSTICK_LIMITED << 8)|DI8DEVTYPE_JOYSTICK
5463 : DIDEVTYPE_HID|(DIDEVTYPEJOYSTICK_UNKNOWN << 8)|DIDEVTYPE_JOYSTICK,
5464 .tszInstanceName = L"Wine test root driver",
5465 .tszProductName = L"Wine test root driver",
5466 .guidFFDriver = GUID_NULL,
5467 .wUsagePage = HID_USAGE_PAGE_GENERIC,
5468 .wUsage = HID_USAGE_GENERIC_JOYSTICK,
5471 .dwSize = sizeof(DIDEVICEINSTANCEW),
5472 .guidInstance = expect_guid_product,
5473 .guidProduct = expect_guid_product,
5474 .dwDevType = version >= 0x800 ? DIDEVTYPE_HID|(DI8DEVTYPEGAMEPAD_STANDARD << 8)|DI8DEVTYPE_GAMEPAD
5475 : DIDEVTYPE_HID|(DIDEVTYPEJOYSTICK_GAMEPAD << 8)|DIDEVTYPE_JOYSTICK,
5476 .tszInstanceName = L"Wine test root driver",
5477 .tszProductName = L"Wine test root driver",
5478 .guidFFDriver = GUID_NULL,
5479 .wUsagePage = HID_USAGE_PAGE_GENERIC,
5480 .wUsage = HID_USAGE_GENERIC_GAMEPAD,
5483 .dwSize = sizeof(DIDEVICEINSTANCEW),
5484 .guidInstance = expect_guid_product,
5485 .guidProduct = expect_guid_product,
5486 .dwDevType = version >= 0x800 ? DIDEVTYPE_HID|(DI8DEVTYPEJOYSTICK_STANDARD << 8)|DI8DEVTYPE_JOYSTICK
5487 : DIDEVTYPE_HID|(DIDEVTYPEJOYSTICK_UNKNOWN << 8)|DIDEVTYPE_JOYSTICK,
5488 .tszInstanceName = L"Wine test root driver",
5489 .tszProductName = L"Wine test root driver",
5490 .guidFFDriver = GUID_NULL,
5491 .wUsagePage = HID_USAGE_PAGE_GENERIC,
5492 .wUsage = HID_USAGE_GENERIC_JOYSTICK,
5496 DIDEVICEINSTANCEW devinst = {.dwSize = sizeof(DIDEVICEINSTANCEW)};
5497 DIDEVCAPS caps = {.dwSize = sizeof(DIDEVCAPS)};
5498 WCHAR cwd[MAX_PATH], tempdir[MAX_PATH];
5499 IDirectInputDevice8W *device;
5500 BOOL success = TRUE;
5501 ULONG i, ref;
5502 HRESULT hr;
5504 winetest_push_context( "version %#x", version );
5506 for (i = 0; i < ARRAY_SIZE(device_desc) && success; ++i)
5508 winetest_push_context( "desc[%d]", i );
5509 GetCurrentDirectoryW( ARRAY_SIZE(cwd), cwd );
5510 GetTempPathW( ARRAY_SIZE(tempdir), tempdir );
5511 SetCurrentDirectoryW( tempdir );
5513 cleanup_registry_keys();
5514 if (!dinput_driver_start( device_desc[i].report_desc_buf, device_desc[i].report_desc_len,
5515 &device_desc[i].hid_caps, NULL, 0 ))
5517 success = FALSE;
5518 goto done;
5521 if (FAILED(hr = create_dinput_device( version, &devinst, &device )))
5523 success = FALSE;
5524 goto done;
5527 hr = IDirectInputDevice8_GetDeviceInfo( device, &devinst );
5528 ok( hr == DI_OK, "GetDeviceInfo returned %#x\n", hr );
5529 check_member( devinst, expect_devinst[i], "%d", dwSize );
5530 todo_wine
5531 check_member_guid( devinst, expect_devinst[i], guidInstance );
5532 check_member_guid( devinst, expect_devinst[i], guidProduct );
5533 todo_wine_if( version <= 0x700 && i == 3 )
5534 check_member( devinst, expect_devinst[i], "%#x", dwDevType );
5535 todo_wine
5536 check_member_wstr( devinst, expect_devinst[i], tszInstanceName );
5537 todo_wine
5538 check_member_wstr( devinst, expect_devinst[i], tszProductName );
5539 check_member_guid( devinst, expect_devinst[i], guidFFDriver );
5540 check_member( devinst, expect_devinst[i], "%04x", wUsagePage );
5541 check_member( devinst, expect_devinst[i], "%04x", wUsage );
5543 hr = IDirectInputDevice8_GetCapabilities( device, &caps );
5544 ok( hr == DI_OK, "GetCapabilities returned %#x\n", hr );
5545 check_member( caps, expect_caps[i], "%d", dwSize );
5546 check_member( caps, expect_caps[i], "%#x", dwFlags );
5547 todo_wine_if( version <= 0x700 && i == 3 )
5548 check_member( caps, expect_caps[i], "%#x", dwDevType );
5549 check_member( caps, expect_caps[i], "%d", dwAxes );
5550 check_member( caps, expect_caps[i], "%d", dwButtons );
5551 check_member( caps, expect_caps[i], "%d", dwPOVs );
5552 check_member( caps, expect_caps[i], "%d", dwFFSamplePeriod );
5553 check_member( caps, expect_caps[i], "%d", dwFFMinTimeResolution );
5554 check_member( caps, expect_caps[i], "%d", dwFirmwareRevision );
5555 check_member( caps, expect_caps[i], "%d", dwHardwareRevision );
5556 check_member( caps, expect_caps[i], "%d", dwFFDriverVersion );
5558 ref = IDirectInputDevice8_Release( device );
5559 ok( ref == 0, "Release returned %d\n", ref );
5561 done:
5562 pnp_driver_stop();
5563 cleanup_registry_keys();
5564 SetCurrentDirectoryW( cwd );
5565 winetest_pop_context();
5568 winetest_pop_context();
5570 return success;
5573 static void test_periodic_effect( IDirectInputDevice8W *device, HANDLE file, DWORD version )
5575 struct hid_expect expect_download[] =
5577 /* set periodic */
5579 .code = IOCTL_HID_WRITE_REPORT,
5580 .report_id = 5,
5581 .report_len = 2,
5582 .report_buf = {0x05,0x19},
5584 /* set envelope */
5586 .code = IOCTL_HID_WRITE_REPORT,
5587 .report_id = 6,
5588 .report_len = 7,
5589 .report_buf = {0x06,0x19,0x4c,0x02,0x00,0x04,0x00},
5591 /* update effect */
5593 .code = IOCTL_HID_WRITE_REPORT,
5594 .report_id = 3,
5595 .report_len = 11,
5596 .report_buf = {0x03,0x01,0x01,0x08,0x01,0x00,version >= 0x700 ? 0x06 : 0x00,0x00,0x01,0x55,0xd5},
5598 /* start command when DIEP_START is set */
5600 .code = IOCTL_HID_WRITE_REPORT,
5601 .report_id = 2,
5602 .report_len = 4,
5603 .report_buf = {0x02,0x01,0x01,0x01},
5606 struct hid_expect expect_download_2[] =
5608 /* set periodic */
5610 .code = IOCTL_HID_WRITE_REPORT,
5611 .report_id = 5,
5612 .report_len = 2,
5613 .report_buf = {0x05,0x19},
5615 /* set envelope */
5617 .code = IOCTL_HID_WRITE_REPORT,
5618 .report_id = 6,
5619 .report_len = 7,
5620 .report_buf = {0x06,0x19,0x4c,0x02,0x00,0x04,0x00},
5622 /* update effect */
5624 .code = IOCTL_HID_WRITE_REPORT,
5625 .report_id = 3,
5626 .report_len = 11,
5627 .report_buf = {0x03,0x01,0x02,0x08,0x01,0x00,version >= 0x700 ? 0x06 : 0x00,0x00,0x01,0x55,0xd5},
5630 struct hid_expect expect_update[] =
5632 /* update effect */
5634 .code = IOCTL_HID_WRITE_REPORT,
5635 .report_id = 3,
5636 .report_len = 11,
5637 .report_buf = {0x03,0x01,0x02,0x08,0xff,0xff,version >= 0x700 ? 0x06 : 0x00,0x00,0x01,0x55,0xd5},
5640 struct hid_expect expect_set_envelope[] =
5642 /* set envelope */
5644 .code = IOCTL_HID_WRITE_REPORT,
5645 .report_id = 6,
5646 .report_len = 7,
5647 .report_buf = {0x06,0x19,0x4c,0x01,0x00,0x04,0x00},
5650 struct hid_expect expect_start =
5652 .code = IOCTL_HID_WRITE_REPORT,
5653 .report_id = 2,
5654 .report_len = 4,
5655 .report_buf = {0x02, 0x01, 0x01, 0x01},
5657 struct hid_expect expect_start_solo =
5659 .code = IOCTL_HID_WRITE_REPORT,
5660 .report_id = 2,
5661 .report_len = 4,
5662 .report_buf = {0x02, 0x01, 0x02, 0x01},
5664 struct hid_expect expect_start_0 =
5666 .code = IOCTL_HID_WRITE_REPORT,
5667 .report_id = 2,
5668 .report_len = 4,
5669 .report_buf = {0x02, 0x01, 0x01, 0x00},
5671 struct hid_expect expect_start_4 =
5673 .code = IOCTL_HID_WRITE_REPORT,
5674 .report_id = 2,
5675 .report_len = 4,
5676 .report_buf = {0x02, 0x01, 0x01, 0x04},
5678 struct hid_expect expect_stop =
5680 .code = IOCTL_HID_WRITE_REPORT,
5681 .report_id = 2,
5682 .report_len = 4,
5683 .report_buf = {0x02, 0x01, 0x03, 0x00},
5685 struct hid_expect expect_unload[] =
5688 .code = IOCTL_HID_WRITE_REPORT,
5689 .report_id = 2,
5690 .report_len = 4,
5691 .report_buf = {0x02,0x01,0x03,0x00},
5693 /* device reset, when unloaded from Unacquire */
5695 .code = IOCTL_HID_WRITE_REPORT,
5696 .report_id = 1,
5697 .report_len = 2,
5698 .report_buf = {1,0x01},
5701 struct hid_expect expect_acquire[] =
5704 .code = IOCTL_HID_WRITE_REPORT,
5705 .report_id = 1,
5706 .report_len = 2,
5707 .report_buf = {1, 0x01},
5710 .code = IOCTL_HID_WRITE_REPORT,
5711 .report_id = 8,
5712 .report_len = 2,
5713 .report_buf = {8, 0x19},
5716 struct hid_expect expect_reset[] =
5719 .code = IOCTL_HID_WRITE_REPORT,
5720 .report_id = 1,
5721 .report_len = 2,
5722 .report_buf = {1, 0x01},
5725 static const DWORD expect_axes_init[2] = {0};
5726 const DIEFFECT expect_desc_init =
5728 .dwSize = version >= 0x700 ? sizeof(DIEFFECT_DX6) : sizeof(DIEFFECT_DX5),
5729 .dwTriggerButton = -1,
5730 .rgdwAxes = (void *)expect_axes_init,
5732 static const DWORD expect_axes[3] =
5734 DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 2 ) | DIDFT_FFACTUATOR,
5735 DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 0 ) | DIDFT_FFACTUATOR,
5736 DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 1 ) | DIDFT_FFACTUATOR,
5738 static const LONG expect_directions[3] =
5740 +3000,
5741 -6000,
5744 static const DIENVELOPE expect_envelope =
5746 .dwSize = sizeof(DIENVELOPE),
5747 .dwAttackLevel = 1000,
5748 .dwAttackTime = 2000,
5749 .dwFadeLevel = 3000,
5750 .dwFadeTime = 4000,
5752 static const DIPERIODIC expect_periodic =
5754 .dwMagnitude = 1000,
5755 .lOffset = 2000,
5756 .dwPhase = 3000,
5757 .dwPeriod = 4000,
5759 const DIEFFECT expect_desc =
5761 .dwSize = version >= 0x700 ? sizeof(DIEFFECT_DX6) : sizeof(DIEFFECT_DX5),
5762 .dwFlags = DIEFF_SPHERICAL | DIEFF_OBJECTIDS,
5763 .dwDuration = 1000,
5764 .dwSamplePeriod = 2000,
5765 .dwGain = 3000,
5766 .dwTriggerButton = DIDFT_PSHBUTTON | DIDFT_MAKEINSTANCE( 0 ) | DIDFT_FFEFFECTTRIGGER,
5767 .dwTriggerRepeatInterval = 5000,
5768 .cAxes = 3,
5769 .rgdwAxes = (void *)expect_axes,
5770 .rglDirection = (void *)expect_directions,
5771 .lpEnvelope = (void *)&expect_envelope,
5772 .cbTypeSpecificParams = sizeof(DIPERIODIC),
5773 .lpvTypeSpecificParams = (void *)&expect_periodic,
5774 .dwStartDelay = 6000,
5776 struct check_created_effect_params check_params = {0};
5777 IDirectInputEffect *effect;
5778 DIPERIODIC periodic = {0};
5779 DIENVELOPE envelope = {0};
5780 LONG directions[4] = {0};
5781 DIEFFECT desc = {0};
5782 DWORD axes[4] = {0};
5783 ULONG i, ref, flags;
5784 HRESULT hr;
5785 GUID guid;
5787 hr = IDirectInputDevice8_CreateEffect( device, &GUID_Sine, NULL, NULL, NULL );
5788 ok( hr == E_POINTER, "CreateEffect returned %#x\n", hr );
5789 hr = IDirectInputDevice8_CreateEffect( device, NULL, NULL, &effect, NULL );
5790 ok( hr == E_POINTER, "CreateEffect returned %#x\n", hr );
5791 hr = IDirectInputDevice8_CreateEffect( device, &GUID_NULL, NULL, &effect, NULL );
5792 ok( hr == DIERR_DEVICENOTREG, "CreateEffect returned %#x\n", hr );
5794 hr = IDirectInputDevice8_CreateEffect( device, &GUID_Sine, NULL, &effect, NULL );
5795 ok( hr == DI_OK, "CreateEffect returned %#x\n", hr );
5796 if (hr != DI_OK) return;
5798 hr = IDirectInputDevice8_EnumCreatedEffectObjects( device, check_no_created_effect_objects, effect, 0xdeadbeef );
5799 ok( hr == DIERR_INVALIDPARAM, "EnumCreatedEffectObjects returned %#x\n", hr );
5800 check_params.expect_effect = effect;
5801 hr = IDirectInputDevice8_EnumCreatedEffectObjects( device, check_created_effect_objects, &check_params, 0 );
5802 ok( hr == DI_OK, "EnumCreatedEffectObjects returned %#x\n", hr );
5803 ok( check_params.count == 1, "got count %u, expected 1\n", check_params.count );
5805 hr = IDirectInputEffect_Initialize( effect, NULL, version, &GUID_Sine );
5806 ok( hr == DIERR_INVALIDPARAM, "Initialize returned %#x\n", hr );
5807 hr = IDirectInputEffect_Initialize( effect, instance, 0x800 - (version - 0x700), &GUID_Sine );
5808 if (version == 0x800)
5810 todo_wine
5811 ok( hr == DIERR_BETADIRECTINPUTVERSION, "Initialize returned %#x\n", hr );
5813 else
5815 todo_wine
5816 ok( hr == DIERR_OLDDIRECTINPUTVERSION, "Initialize returned %#x\n", hr );
5818 hr = IDirectInputEffect_Initialize( effect, instance, 0, &GUID_Sine );
5819 todo_wine
5820 ok( hr == DIERR_NOTINITIALIZED, "Initialize returned %#x\n", hr );
5821 hr = IDirectInputEffect_Initialize( effect, instance, version, NULL );
5822 ok( hr == E_POINTER, "Initialize returned %#x\n", hr );
5824 hr = IDirectInputEffect_Initialize( effect, instance, version, &GUID_NULL );
5825 ok( hr == DIERR_DEVICENOTREG, "Initialize returned %#x\n", hr );
5826 hr = IDirectInputEffect_Initialize( effect, instance, version, &GUID_Sine );
5827 ok( hr == DI_OK, "Initialize returned %#x\n", hr );
5828 hr = IDirectInputEffect_Initialize( effect, instance, version, &GUID_Square );
5829 ok( hr == DI_OK, "Initialize returned %#x\n", hr );
5831 hr = IDirectInputEffect_GetEffectGuid( effect, NULL );
5832 ok( hr == E_POINTER, "GetEffectGuid returned %#x\n", hr );
5833 hr = IDirectInputEffect_GetEffectGuid( effect, &guid );
5834 ok( hr == DI_OK, "GetEffectGuid returned %#x\n", hr );
5835 ok( IsEqualGUID( &guid, &GUID_Square ), "got guid %s, expected %s\n", debugstr_guid( &guid ),
5836 debugstr_guid( &GUID_Square ) );
5838 hr = IDirectInputEffect_GetParameters( effect, NULL, 0 );
5839 ok( hr == DI_OK, "GetParameters returned %#x\n", hr );
5840 hr = IDirectInputEffect_GetParameters( effect, NULL, DIEP_DURATION );
5841 ok( hr == DI_OK, "GetParameters returned %#x\n", hr );
5842 hr = IDirectInputEffect_GetParameters( effect, &desc, 0 );
5843 ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#x\n", hr );
5844 desc.dwSize = sizeof(DIEFFECT_DX5) + 2;
5845 hr = IDirectInputEffect_GetParameters( effect, &desc, 0 );
5846 ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#x\n", hr );
5847 desc.dwSize = sizeof(DIEFFECT_DX5);
5848 hr = IDirectInputEffect_GetParameters( effect, &desc, 0 );
5849 ok( hr == DI_OK, "GetParameters returned %#x\n", hr );
5850 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_STARTDELAY );
5851 ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#x\n", hr );
5852 desc.dwSize = sizeof(DIEFFECT_DX6);
5853 hr = IDirectInputEffect_GetParameters( effect, &desc, 0 );
5854 ok( hr == DI_OK, "GetParameters returned %#x\n", hr );
5856 set_hid_expect( file, expect_reset, sizeof(expect_reset) );
5857 hr = IDirectInputDevice8_Unacquire( device );
5858 ok( hr == DI_OK, "Unacquire returned: %#x\n", hr );
5859 set_hid_expect( file, NULL, 0 );
5860 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DURATION );
5861 ok( hr == DI_OK, "GetParameters returned %#x\n", hr );
5862 set_hid_expect( file, expect_acquire, sizeof(expect_acquire) );
5863 hr = IDirectInputDevice8_Acquire( device );
5864 ok( hr == DI_OK, "Acquire returned: %#x\n", hr );
5865 wait_hid_expect( file, 100 ); /* device gain reports are written asynchronously */
5867 desc.dwDuration = 0xdeadbeef;
5868 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DURATION );
5869 ok( hr == DI_OK, "GetParameters returned %#x\n", hr );
5870 check_member( desc, expect_desc_init, "%u", dwDuration );
5871 memset( &desc, 0xcd, sizeof(desc) );
5872 desc.dwSize = version >= 0x700 ? sizeof(DIEFFECT_DX6) : sizeof(DIEFFECT_DX5);
5873 desc.dwFlags = 0;
5874 desc.dwStartDelay = 0xdeadbeef;
5875 flags = DIEP_GAIN | DIEP_SAMPLEPERIOD | DIEP_TRIGGERREPEATINTERVAL |
5876 (version >= 0x700 ? DIEP_STARTDELAY : 0);
5877 hr = IDirectInputEffect_GetParameters( effect, &desc, flags );
5878 ok( hr == DI_OK, "GetParameters returned %#x\n", hr );
5879 check_member( desc, expect_desc_init, "%u", dwSamplePeriod );
5880 check_member( desc, expect_desc_init, "%u", dwGain );
5881 if (version >= 0x700) check_member( desc, expect_desc_init, "%u", dwStartDelay );
5882 else ok( desc.dwStartDelay == 0xdeadbeef, "got dwStartDelay %#x\n", desc.dwStartDelay );
5883 check_member( desc, expect_desc_init, "%u", dwTriggerRepeatInterval );
5885 memset( &desc, 0xcd, sizeof(desc) );
5886 desc.dwSize = version >= 0x700 ? sizeof(DIEFFECT_DX6) : sizeof(DIEFFECT_DX5);
5887 desc.dwFlags = 0;
5888 desc.lpEnvelope = NULL;
5889 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_ENVELOPE );
5890 ok( hr == E_POINTER, "GetParameters returned %#x\n", hr );
5891 desc.lpEnvelope = &envelope;
5892 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_ENVELOPE );
5893 ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#x\n", hr );
5894 envelope.dwSize = sizeof(DIENVELOPE);
5895 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_ENVELOPE );
5896 ok( hr == DI_OK, "GetParameters returned %#x\n", hr );
5898 desc.dwFlags = 0;
5899 desc.cAxes = 0;
5900 desc.rgdwAxes = NULL;
5901 desc.rglDirection = NULL;
5902 desc.lpEnvelope = NULL;
5903 desc.cbTypeSpecificParams = 0;
5904 desc.lpvTypeSpecificParams = NULL;
5905 hr = IDirectInputEffect_GetParameters( effect, &desc, version >= 0x700 ? DIEP_ALLPARAMS : DIEP_ALLPARAMS_DX5 );
5906 ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#x\n", hr );
5907 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_TRIGGERBUTTON );
5908 ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#x\n", hr );
5909 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_AXES );
5910 ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#x\n", hr );
5911 desc.dwFlags = DIEFF_OBJECTOFFSETS;
5912 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
5913 ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#x\n", hr );
5914 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_TRIGGERBUTTON );
5915 ok( hr == DI_OK, "GetParameters returned %#x\n", hr );
5916 check_member( desc, expect_desc_init, "%#x", dwTriggerButton );
5917 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_AXES );
5918 ok( hr == DI_OK, "GetParameters returned %#x\n", hr );
5919 check_member( desc, expect_desc_init, "%u", cAxes );
5920 desc.dwFlags = DIEFF_OBJECTIDS;
5921 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
5922 ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#x\n", hr );
5923 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_TRIGGERBUTTON );
5924 ok( hr == DI_OK, "GetParameters returned %#x\n", hr );
5925 check_member( desc, expect_desc_init, "%#x", dwTriggerButton );
5926 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_AXES );
5927 ok( hr == DI_OK, "GetParameters returned %#x\n", hr );
5928 check_member( desc, expect_desc_init, "%u", cAxes );
5929 desc.dwFlags |= DIEFF_CARTESIAN;
5930 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
5931 ok( hr == DI_OK, "GetParameters returned %#x\n", hr );
5932 ok( desc.dwFlags == DIEFF_OBJECTIDS, "got flags %#x, expected %#x\n", desc.dwFlags, DIEFF_OBJECTIDS );
5933 desc.dwFlags |= DIEFF_POLAR;
5934 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
5935 ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#x\n", hr );
5936 ok( desc.dwFlags == DIEFF_OBJECTIDS, "got flags %#x, expected %#x\n", desc.dwFlags, DIEFF_OBJECTIDS );
5937 desc.dwFlags |= DIEFF_SPHERICAL;
5938 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
5939 ok( hr == DI_OK, "GetParameters returned %#x\n", hr );
5940 check_member( desc, expect_desc_init, "%u", cAxes );
5941 ok( desc.dwFlags == DIEFF_OBJECTIDS, "got flags %#x, expected %#x\n", desc.dwFlags, DIEFF_OBJECTIDS );
5943 desc.dwFlags |= DIEFF_SPHERICAL;
5944 desc.cAxes = 2;
5945 desc.rgdwAxes = axes;
5946 desc.rglDirection = directions;
5947 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_AXES | DIEP_DIRECTION );
5948 ok( hr == DI_OK, "GetParameters returned %#x\n", hr );
5949 check_member( desc, expect_desc_init, "%u", cAxes );
5950 check_member( desc, expect_desc_init, "%u", rgdwAxes[0] );
5951 check_member( desc, expect_desc_init, "%u", rgdwAxes[1] );
5952 check_member( desc, expect_desc_init, "%p", rglDirection );
5953 ok( desc.dwFlags == DIEFF_OBJECTIDS, "got flags %#x, expected %#x\n", desc.dwFlags, DIEFF_OBJECTIDS );
5955 desc.dwFlags |= DIEFF_SPHERICAL;
5956 desc.lpEnvelope = &envelope;
5957 desc.cbTypeSpecificParams = sizeof(periodic);
5958 desc.lpvTypeSpecificParams = &periodic;
5959 hr = IDirectInputEffect_GetParameters( effect, &desc, version >= 0x700 ? DIEP_ALLPARAMS : DIEP_ALLPARAMS_DX5 );
5960 ok( hr == DI_OK, "GetParameters returned %#x\n", hr );
5961 check_member( desc, expect_desc_init, "%u", dwDuration );
5962 check_member( desc, expect_desc_init, "%u", dwSamplePeriod );
5963 check_member( desc, expect_desc_init, "%u", dwGain );
5964 check_member( desc, expect_desc_init, "%#x", dwTriggerButton );
5965 check_member( desc, expect_desc_init, "%u", dwTriggerRepeatInterval );
5966 check_member( desc, expect_desc_init, "%u", cAxes );
5967 check_member( desc, expect_desc_init, "%u", rgdwAxes[0] );
5968 check_member( desc, expect_desc_init, "%u", rgdwAxes[1] );
5969 check_member( desc, expect_desc_init, "%p", rglDirection );
5970 todo_wine
5971 check_member( desc, expect_desc_init, "%p", lpEnvelope );
5972 todo_wine
5973 check_member( desc, expect_desc_init, "%u", cbTypeSpecificParams );
5974 if (version >= 0x700) check_member( desc, expect_desc_init, "%u", dwStartDelay );
5975 else ok( desc.dwStartDelay == 0xcdcdcdcd, "got dwStartDelay %#x\n", desc.dwStartDelay );
5977 set_hid_expect( file, expect_reset, sizeof(expect_reset) );
5978 hr = IDirectInputDevice8_Unacquire( device );
5979 ok( hr == DI_OK, "Unacquire returned: %#x\n", hr );
5980 set_hid_expect( file, NULL, 0 );
5981 hr = IDirectInputEffect_Download( effect );
5982 ok( hr == DIERR_NOTEXCLUSIVEACQUIRED, "Download returned %#x\n", hr );
5983 set_hid_expect( file, expect_acquire, sizeof(expect_acquire) );
5984 hr = IDirectInputDevice8_Acquire( device );
5985 ok( hr == DI_OK, "Acquire returned: %#x\n", hr );
5986 wait_hid_expect( file, 100 ); /* device gain reports are written asynchronously */
5988 hr = IDirectInputEffect_Download( effect );
5989 ok( hr == DIERR_INCOMPLETEEFFECT, "Download returned %#x\n", hr );
5990 hr = IDirectInputEffect_Unload( effect );
5991 ok( hr == DI_NOEFFECT, "Unload returned %#x\n", hr );
5993 hr = IDirectInputEffect_SetParameters( effect, NULL, DIEP_NODOWNLOAD );
5994 ok( hr == E_POINTER, "SetParameters returned %#x\n", hr );
5995 memset( &desc, 0, sizeof(desc) );
5996 hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_NODOWNLOAD );
5997 ok( hr == DIERR_INVALIDPARAM, "SetParameters returned %#x\n", hr );
5998 desc.dwSize = version >= 0x700 ? sizeof(DIEFFECT_DX6) : sizeof(DIEFFECT_DX5);
5999 hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_NODOWNLOAD );
6000 ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#x\n", hr );
6002 set_hid_expect( file, expect_reset, sizeof(expect_reset) );
6003 hr = IDirectInputDevice8_Unacquire( device );
6004 ok( hr == DI_OK, "Unacquire returned: %#x\n", hr );
6005 set_hid_expect( file, NULL, 0 );
6006 hr = IDirectInputEffect_SetParameters( effect, &expect_desc, DIEP_DURATION );
6007 ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#x\n", hr );
6008 set_hid_expect( file, expect_acquire, sizeof(expect_acquire) );
6009 hr = IDirectInputDevice8_Acquire( device );
6010 ok( hr == DI_OK, "Acquire returned: %#x\n", hr );
6011 wait_hid_expect( file, 100 ); /* device gain reports are written asynchronously */
6013 hr = IDirectInputEffect_SetParameters( effect, &expect_desc, DIEP_DURATION | DIEP_NODOWNLOAD );
6014 ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#x\n", hr );
6016 desc.dwTriggerButton = -1;
6017 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DURATION );
6018 ok( hr == DI_OK, "GetParameters returned %#x\n", hr );
6019 check_member( desc, expect_desc, "%u", dwDuration );
6020 check_member( desc, expect_desc_init, "%u", dwSamplePeriod );
6021 check_member( desc, expect_desc_init, "%u", dwGain );
6022 check_member( desc, expect_desc_init, "%#x", dwTriggerButton );
6023 check_member( desc, expect_desc_init, "%u", dwTriggerRepeatInterval );
6024 check_member( desc, expect_desc_init, "%u", cAxes );
6025 check_member( desc, expect_desc_init, "%p", rglDirection );
6026 check_member( desc, expect_desc_init, "%p", lpEnvelope );
6027 check_member( desc, expect_desc_init, "%u", cbTypeSpecificParams );
6028 check_member( desc, expect_desc_init, "%u", dwStartDelay );
6030 hr = IDirectInputEffect_Download( effect );
6031 ok( hr == DIERR_INCOMPLETEEFFECT, "Download returned %#x\n", hr );
6032 hr = IDirectInputEffect_Unload( effect );
6033 ok( hr == DI_NOEFFECT, "Unload returned %#x\n", hr );
6035 flags = DIEP_GAIN | DIEP_SAMPLEPERIOD | DIEP_TRIGGERREPEATINTERVAL | DIEP_NODOWNLOAD;
6036 if (version >= 0x700) flags |= DIEP_STARTDELAY;
6037 hr = IDirectInputEffect_SetParameters( effect, &expect_desc, flags );
6038 ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#x\n", hr );
6039 desc.dwDuration = 0;
6040 flags = DIEP_DURATION | DIEP_GAIN | DIEP_SAMPLEPERIOD | DIEP_TRIGGERREPEATINTERVAL;
6041 if (version >= 0x700) flags |= DIEP_STARTDELAY;
6042 hr = IDirectInputEffect_GetParameters( effect, &desc, flags );
6043 ok( hr == DI_OK, "GetParameters returned %#x\n", hr );
6044 check_member( desc, expect_desc, "%u", dwDuration );
6045 check_member( desc, expect_desc, "%u", dwSamplePeriod );
6046 check_member( desc, expect_desc, "%u", dwGain );
6047 check_member( desc, expect_desc_init, "%#x", dwTriggerButton );
6048 check_member( desc, expect_desc, "%u", dwTriggerRepeatInterval );
6049 check_member( desc, expect_desc_init, "%u", cAxes );
6050 check_member( desc, expect_desc_init, "%p", rglDirection );
6051 check_member( desc, expect_desc_init, "%p", lpEnvelope );
6052 check_member( desc, expect_desc_init, "%u", cbTypeSpecificParams );
6053 if (version >= 0x700) check_member( desc, expect_desc, "%u", dwStartDelay );
6054 else ok( desc.dwStartDelay == 0, "got dwStartDelay %#x\n", desc.dwStartDelay );
6056 hr = IDirectInputEffect_Download( effect );
6057 ok( hr == DIERR_INCOMPLETEEFFECT, "Download returned %#x\n", hr );
6058 hr = IDirectInputEffect_Unload( effect );
6059 ok( hr == DI_NOEFFECT, "Unload returned %#x\n", hr );
6061 desc.lpEnvelope = NULL;
6062 hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_ENVELOPE | DIEP_NODOWNLOAD );
6063 ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#x\n", hr );
6064 desc.lpEnvelope = &envelope;
6065 envelope.dwSize = 0;
6066 hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_ENVELOPE | DIEP_NODOWNLOAD );
6067 ok( hr == DIERR_INVALIDPARAM, "SetParameters returned %#x\n", hr );
6069 hr = IDirectInputEffect_SetParameters( effect, &expect_desc, DIEP_ENVELOPE | DIEP_NODOWNLOAD );
6070 ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#x\n", hr );
6072 desc.lpEnvelope = &envelope;
6073 envelope.dwSize = sizeof(DIENVELOPE);
6074 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_ENVELOPE );
6075 ok( hr == DI_OK, "GetParameters returned %#x\n", hr );
6076 check_member( envelope, expect_envelope, "%u", dwAttackLevel );
6077 check_member( envelope, expect_envelope, "%u", dwAttackTime );
6078 check_member( envelope, expect_envelope, "%u", dwFadeLevel );
6079 check_member( envelope, expect_envelope, "%u", dwFadeTime );
6081 hr = IDirectInputEffect_Download( effect );
6082 ok( hr == DIERR_INCOMPLETEEFFECT, "Download returned %#x\n", hr );
6083 hr = IDirectInputEffect_Unload( effect );
6084 ok( hr == DI_NOEFFECT, "Unload returned %#x\n", hr );
6086 desc.dwFlags = 0;
6087 desc.cAxes = 0;
6088 desc.rgdwAxes = NULL;
6089 desc.rglDirection = NULL;
6090 desc.lpEnvelope = NULL;
6091 desc.cbTypeSpecificParams = 0;
6092 desc.lpvTypeSpecificParams = NULL;
6093 flags = version >= 0x700 ? DIEP_ALLPARAMS : DIEP_ALLPARAMS_DX5;
6094 hr = IDirectInputEffect_SetParameters( effect, &desc, flags | DIEP_NODOWNLOAD );
6095 ok( hr == DIERR_INVALIDPARAM, "SetParameters returned %#x\n", hr );
6096 hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_TRIGGERBUTTON | DIEP_NODOWNLOAD );
6097 ok( hr == DIERR_INVALIDPARAM, "SetParameters returned %#x\n", hr );
6098 hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_AXES | DIEP_NODOWNLOAD );
6099 ok( hr == DIERR_INVALIDPARAM, "SetParameters returned %#x\n", hr );
6101 desc.dwFlags = DIEFF_OBJECTOFFSETS;
6102 desc.cAxes = 1;
6103 desc.rgdwAxes = axes;
6104 desc.rgdwAxes[0] = DIJOFS_X;
6105 desc.dwTriggerButton = DIJOFS_BUTTON( 1 );
6106 hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_DIRECTION | DIEP_NODOWNLOAD );
6107 ok( hr == DIERR_INVALIDPARAM, "SetParameters returned %#x\n", hr );
6108 hr = IDirectInputEffect_SetParameters( effect, &expect_desc, DIEP_AXES | DIEP_TRIGGERBUTTON | DIEP_NODOWNLOAD );
6109 ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#x\n", hr );
6110 hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_AXES | DIEP_TRIGGERBUTTON | DIEP_NODOWNLOAD );
6111 ok( hr == DIERR_ALREADYINITIALIZED, "SetParameters returned %#x\n", hr );
6113 desc.cAxes = 0;
6114 desc.dwFlags = DIEFF_OBJECTIDS;
6115 desc.rgdwAxes = axes;
6116 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_AXES | DIEP_TRIGGERBUTTON );
6117 ok( hr == DIERR_MOREDATA, "GetParameters returned %#x\n", hr );
6118 check_member( desc, expect_desc, "%u", cAxes );
6119 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_AXES | DIEP_TRIGGERBUTTON );
6120 ok( hr == DI_OK, "GetParameters returned %#x\n", hr );
6121 check_member( desc, expect_desc, "%#x", dwTriggerButton );
6122 check_member( desc, expect_desc, "%u", cAxes );
6123 check_member( desc, expect_desc, "%u", rgdwAxes[0] );
6124 check_member( desc, expect_desc, "%u", rgdwAxes[1] );
6125 check_member( desc, expect_desc, "%u", rgdwAxes[2] );
6127 desc.dwFlags = DIEFF_OBJECTOFFSETS;
6128 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_AXES | DIEP_TRIGGERBUTTON );
6129 ok( hr == DI_OK, "GetParameters returned %#x\n", hr );
6130 ok( desc.dwTriggerButton == 0x30, "got %#x expected %#x\n", desc.dwTriggerButton, 0x30 );
6131 ok( desc.rgdwAxes[0] == 8, "got %#x expected %#x\n", desc.rgdwAxes[0], 8 );
6132 ok( desc.rgdwAxes[1] == 0, "got %#x expected %#x\n", desc.rgdwAxes[1], 0 );
6133 ok( desc.rgdwAxes[2] == 4, "got %#x expected %#x\n", desc.rgdwAxes[2], 4 );
6135 hr = IDirectInputEffect_Download( effect );
6136 ok( hr == DIERR_INCOMPLETEEFFECT, "Download returned %#x\n", hr );
6137 hr = IDirectInputEffect_Unload( effect );
6138 ok( hr == DI_NOEFFECT, "Unload returned %#x\n", hr );
6140 desc.dwFlags = DIEFF_CARTESIAN;
6141 desc.cAxes = 0;
6142 desc.rglDirection = directions;
6143 hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_DIRECTION | DIEP_NODOWNLOAD );
6144 ok( hr == DIERR_INVALIDPARAM, "SetParameters returned %#x\n", hr );
6145 desc.cAxes = 3;
6146 hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_DIRECTION | DIEP_NODOWNLOAD );
6147 ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#x\n", hr );
6148 desc.dwFlags = DIEFF_POLAR;
6149 desc.cAxes = 3;
6150 hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_DIRECTION | DIEP_NODOWNLOAD );
6151 ok( hr == DIERR_INVALIDPARAM, "SetParameters returned %#x\n", hr );
6153 hr = IDirectInputEffect_SetParameters( effect, &expect_desc, DIEP_DIRECTION | DIEP_NODOWNLOAD );
6154 ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#x\n", hr );
6156 desc.dwFlags = DIEFF_SPHERICAL;
6157 desc.cAxes = 1;
6158 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
6159 ok( hr == DIERR_MOREDATA, "GetParameters returned %#x\n", hr );
6160 ok( desc.dwFlags == DIEFF_SPHERICAL, "got flags %#x, expected %#x\n", desc.dwFlags, DIEFF_SPHERICAL );
6161 check_member( desc, expect_desc, "%u", cAxes );
6162 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
6163 ok( hr == DI_OK, "GetParameters returned %#x\n", hr );
6164 check_member( desc, expect_desc, "%u", cAxes );
6165 ok( desc.rglDirection[0] == 3000, "got rglDirection[0] %d expected %d\n", desc.rglDirection[0], 3000 );
6166 ok( desc.rglDirection[1] == 30000, "got rglDirection[1] %d expected %d\n", desc.rglDirection[1], 30000 );
6167 ok( desc.rglDirection[2] == 0, "got rglDirection[2] %d expected %d\n", desc.rglDirection[2], 0 );
6168 desc.dwFlags = DIEFF_CARTESIAN;
6169 desc.cAxes = 2;
6170 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
6171 ok( hr == DIERR_MOREDATA, "GetParameters returned %#x\n", hr );
6172 ok( desc.dwFlags == DIEFF_CARTESIAN, "got flags %#x, expected %#x\n", desc.dwFlags, DIEFF_CARTESIAN );
6173 check_member( desc, expect_desc, "%u", cAxes );
6174 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
6175 ok( hr == DI_OK, "GetParameters returned %#x\n", hr );
6176 check_member( desc, expect_desc, "%u", cAxes );
6177 ok( desc.rglDirection[0] == 4330, "got rglDirection[0] %d expected %d\n", desc.rglDirection[0], 4330 );
6178 ok( desc.rglDirection[1] == 2500, "got rglDirection[1] %d expected %d\n", desc.rglDirection[1], 2500 );
6179 ok( desc.rglDirection[2] == -8660, "got rglDirection[2] %d expected %d\n", desc.rglDirection[2], -8660 );
6180 desc.dwFlags = DIEFF_POLAR;
6181 desc.cAxes = 3;
6182 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
6183 ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#x\n", hr );
6185 hr = IDirectInputEffect_Download( effect );
6186 ok( hr == DIERR_INCOMPLETEEFFECT, "Download returned %#x\n", hr );
6187 hr = IDirectInputEffect_Unload( effect );
6188 ok( hr == DI_NOEFFECT, "Unload returned %#x\n", hr );
6190 desc.cbTypeSpecificParams = 0;
6191 desc.lpvTypeSpecificParams = &periodic;
6192 hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_TYPESPECIFICPARAMS | DIEP_NODOWNLOAD );
6193 ok( hr == DIERR_INVALIDPARAM, "SetParameters returned %#x\n", hr );
6194 desc.cbTypeSpecificParams = sizeof(DIPERIODIC);
6195 hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_TYPESPECIFICPARAMS | DIEP_NODOWNLOAD );
6196 ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#x\n", hr );
6197 hr = IDirectInputEffect_SetParameters( effect, &expect_desc, DIEP_TYPESPECIFICPARAMS | DIEP_NODOWNLOAD );
6198 ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#x\n", hr );
6200 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_TYPESPECIFICPARAMS );
6201 ok( hr == DI_OK, "GetParameters returned %#x\n", hr );
6202 check_member( periodic, expect_periodic, "%u", dwMagnitude );
6203 check_member( periodic, expect_periodic, "%d", lOffset );
6204 check_member( periodic, expect_periodic, "%u", dwPhase );
6205 check_member( periodic, expect_periodic, "%u", dwPeriod );
6207 hr = IDirectInputEffect_Start( effect, 1, DIES_NODOWNLOAD );
6208 ok( hr == DIERR_NOTDOWNLOADED, "Start returned %#x\n", hr );
6209 hr = IDirectInputEffect_Stop( effect );
6210 ok( hr == DIERR_NOTDOWNLOADED, "Stop returned %#x\n", hr );
6212 set_hid_expect( file, expect_download, 3 * sizeof(struct hid_expect) );
6213 hr = IDirectInputEffect_Download( effect );
6214 ok( hr == DI_OK, "Download returned %#x\n", hr );
6215 set_hid_expect( file, NULL, 0 );
6217 hr = IDirectInputEffect_Download( effect );
6218 ok( hr == DI_NOEFFECT, "Download returned %#x\n", hr );
6220 hr = IDirectInputEffect_Start( effect, 1, 0xdeadbeef );
6221 ok( hr == DIERR_INVALIDPARAM, "Start returned %#x\n", hr );
6223 set_hid_expect( file, &expect_start_solo, sizeof(expect_start_solo) );
6224 hr = IDirectInputEffect_Start( effect, 1, DIES_SOLO );
6225 ok( hr == DI_OK, "Start returned %#x\n", hr );
6226 set_hid_expect( file, NULL, 0 );
6228 set_hid_expect( file, &expect_stop, sizeof(expect_stop) );
6229 hr = IDirectInputEffect_Stop( effect );
6230 ok( hr == DI_OK, "Stop returned %#x\n", hr );
6231 set_hid_expect( file, NULL, 0 );
6233 set_hid_expect( file, &expect_start, sizeof(expect_start) );
6234 hr = IDirectInputEffect_Start( effect, 1, 0 );
6235 ok( hr == DI_OK, "Start returned %#x\n", hr );
6236 set_hid_expect( file, NULL, 0 );
6238 set_hid_expect( file, &expect_start_4, sizeof(expect_start_4) );
6239 hr = IDirectInputEffect_Start( effect, 4, 0 );
6240 ok( hr == DI_OK, "Start returned %#x\n", hr );
6241 set_hid_expect( file, NULL, 0 );
6243 set_hid_expect( file, &expect_start_0, sizeof(expect_start_4) );
6244 hr = IDirectInputEffect_Start( effect, 0, 0 );
6245 ok( hr == DI_OK, "Start returned %#x\n", hr );
6246 set_hid_expect( file, NULL, 0 );
6248 set_hid_expect( file, expect_unload, sizeof(struct hid_expect) );
6249 hr = IDirectInputEffect_Unload( effect );
6250 ok( hr == DI_OK, "Unload returned %#x\n", hr );
6251 set_hid_expect( file, NULL, 0 );
6253 set_hid_expect( file, expect_download, 4 * sizeof(struct hid_expect) );
6254 hr = IDirectInputEffect_SetParameters( effect, &expect_desc, DIEP_START );
6255 ok( hr == DI_OK, "SetParameters returned %#x\n", hr );
6256 set_hid_expect( file, NULL, 0 );
6258 set_hid_expect( file, expect_unload, sizeof(struct hid_expect) );
6259 hr = IDirectInputEffect_Unload( effect );
6260 ok( hr == DI_OK, "Unload returned %#x\n", hr );
6261 set_hid_expect( file, NULL, 0 );
6263 set_hid_expect( file, expect_download, 3 * sizeof(struct hid_expect) );
6264 hr = IDirectInputEffect_Download( effect );
6265 ok( hr == DI_OK, "Download returned %#x\n", hr );
6266 set_hid_expect( file, NULL, 0 );
6268 set_hid_expect( file, expect_unload, 2 * sizeof(struct hid_expect) );
6269 hr = IDirectInputDevice8_Unacquire( device );
6270 ok( hr == DI_OK, "Unacquire returned: %#x\n", hr );
6271 set_hid_expect( file, NULL, 0 );
6273 hr = IDirectInputEffect_Start( effect, 1, DIES_NODOWNLOAD );
6274 ok( hr == DIERR_NOTEXCLUSIVEACQUIRED, "Start returned %#x\n", hr );
6275 hr = IDirectInputEffect_Stop( effect );
6276 ok( hr == DIERR_NOTEXCLUSIVEACQUIRED, "Stop returned %#x\n", hr );
6278 set_hid_expect( file, expect_acquire, sizeof(expect_acquire) );
6279 hr = IDirectInputDevice8_Acquire( device );
6280 ok( hr == DI_OK, "Acquire returned: %#x\n", hr );
6281 wait_hid_expect( file, 100 ); /* device gain reports are written asynchronously */
6283 hr = IDirectInputEffect_Unload( effect );
6284 ok( hr == DI_NOEFFECT, "Unload returned %#x\n", hr );
6286 ref = IDirectInputEffect_Release( effect );
6287 ok( ref == 0, "Release returned %d\n", ref );
6289 hr = IDirectInputDevice8_CreateEffect( device, &GUID_Sine, NULL, &effect, NULL );
6290 ok( hr == DI_OK, "CreateEffect returned %#x\n", hr );
6292 desc.dwFlags = DIEFF_POLAR | DIEFF_OBJECTIDS;
6293 desc.cAxes = 2;
6294 desc.rgdwAxes[0] = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 2 ) | DIDFT_FFACTUATOR;
6295 desc.rgdwAxes[1] = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 0 ) | DIDFT_FFACTUATOR;
6296 desc.rglDirection[0] = 3000;
6297 desc.rglDirection[1] = 0;
6298 desc.rglDirection[2] = 0;
6299 hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_AXES | DIEP_DIRECTION | DIEP_NODOWNLOAD );
6300 ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#x\n", hr );
6301 desc.rglDirection[0] = 0;
6303 desc.dwFlags = DIEFF_SPHERICAL;
6304 desc.cAxes = 1;
6305 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
6306 ok( hr == DIERR_MOREDATA, "GetParameters returned %#x\n", hr );
6307 ok( desc.dwFlags == DIEFF_SPHERICAL, "got flags %#x, expected %#x\n", desc.dwFlags, DIEFF_SPHERICAL );
6308 ok( desc.cAxes == 2, "got cAxes %u expected 2\n", desc.cAxes );
6309 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
6310 ok( hr == DI_OK, "GetParameters returned %#x\n", hr );
6311 ok( desc.cAxes == 2, "got cAxes %u expected 2\n", desc.cAxes );
6312 ok( desc.rglDirection[0] == 30000, "got rglDirection[0] %d expected %d\n", desc.rglDirection[0], 30000 );
6313 ok( desc.rglDirection[1] == 0, "got rglDirection[1] %d expected %d\n", desc.rglDirection[1], 0 );
6314 ok( desc.rglDirection[2] == 0, "got rglDirection[2] %d expected %d\n", desc.rglDirection[2], 0 );
6316 desc.dwFlags = DIEFF_CARTESIAN;
6317 desc.cAxes = 1;
6318 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
6319 ok( hr == DIERR_MOREDATA, "GetParameters returned %#x\n", hr );
6320 ok( desc.dwFlags == DIEFF_CARTESIAN, "got flags %#x, expected %#x\n", desc.dwFlags, DIEFF_CARTESIAN );
6321 ok( desc.cAxes == 2, "got cAxes %u expected 2\n", desc.cAxes );
6322 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
6323 ok( hr == DI_OK, "GetParameters returned %#x\n", hr );
6324 ok( desc.cAxes == 2, "got cAxes %u expected 2\n", desc.cAxes );
6325 ok( desc.rglDirection[0] == 5000, "got rglDirection[0] %d expected %d\n", desc.rglDirection[0], 5000 );
6326 ok( desc.rglDirection[1] == -8660, "got rglDirection[1] %d expected %d\n", desc.rglDirection[1], -8660 );
6327 ok( desc.rglDirection[2] == 0, "got rglDirection[2] %d expected %d\n", desc.rglDirection[2], 0 );
6329 desc.dwFlags = DIEFF_POLAR;
6330 desc.cAxes = 1;
6331 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
6332 ok( hr == DIERR_MOREDATA, "GetParameters returned %#x\n", hr );
6333 ok( desc.dwFlags == DIEFF_POLAR, "got flags %#x, expected %#x\n", desc.dwFlags, DIEFF_POLAR );
6334 ok( desc.cAxes == 2, "got cAxes %u expected 2\n", desc.cAxes );
6335 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
6336 ok( hr == DI_OK, "GetParameters returned %#x\n", hr );
6337 ok( desc.cAxes == 2, "got cAxes %u expected 2\n", desc.cAxes );
6338 ok( desc.rglDirection[0] == 3000, "got rglDirection[0] %d expected %d\n", desc.rglDirection[0], 3000 );
6339 ok( desc.rglDirection[1] == 0, "got rglDirection[1] %d expected %d\n", desc.rglDirection[1], 0 );
6340 ok( desc.rglDirection[2] == 0, "got rglDirection[2] %d expected %d\n", desc.rglDirection[2], 0 );
6342 ref = IDirectInputEffect_Release( effect );
6343 ok( ref == 0, "Release returned %d\n", ref );
6345 for (i = 1; i < 4; i++)
6347 winetest_push_context( "%u axes", i );
6348 hr = IDirectInputDevice8_CreateEffect( device, &GUID_Sine, NULL, &effect, NULL );
6349 ok( hr == DI_OK, "CreateEffect returned %#x\n", hr );
6351 desc.dwFlags = DIEFF_OBJECTIDS;
6352 desc.cAxes = i;
6353 desc.rgdwAxes[0] = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 2 ) | DIDFT_FFACTUATOR;
6354 desc.rgdwAxes[1] = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 0 ) | DIDFT_FFACTUATOR;
6355 desc.rgdwAxes[2] = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 1 ) | DIDFT_FFACTUATOR;
6356 desc.rglDirection[0] = 0;
6357 desc.rglDirection[1] = 0;
6358 desc.rglDirection[2] = 0;
6359 hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_AXES | DIEP_NODOWNLOAD );
6360 ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#x\n", hr );
6362 desc.dwFlags = DIEFF_CARTESIAN;
6363 desc.cAxes = i == 3 ? 2 : 3;
6364 desc.rglDirection[0] = 1000;
6365 desc.rglDirection[1] = 2000;
6366 desc.rglDirection[2] = 3000;
6367 hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_DIRECTION | DIEP_NODOWNLOAD );
6368 ok( hr == DIERR_INVALIDPARAM, "SetParameters returned %#x\n", hr );
6369 desc.cAxes = i;
6370 hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_DIRECTION | DIEP_NODOWNLOAD );
6371 ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#x\n", hr );
6373 desc.dwFlags = DIEFF_SPHERICAL;
6374 desc.cAxes = i;
6375 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
6376 ok( hr == DI_OK, "GetParameters returned %#x\n", hr );
6377 desc.cAxes = 3;
6378 memset( desc.rglDirection, 0xcd, 3 * sizeof(LONG) );
6379 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
6380 ok( hr == DI_OK, "GetParameters returned %#x\n", hr );
6381 ok( desc.cAxes == i, "got cAxes %u expected 2\n", desc.cAxes );
6382 if (i == 1)
6384 ok( desc.rglDirection[0] == 0, "got rglDirection[0] %d expected %d\n", desc.rglDirection[0], 0 );
6385 ok( desc.rglDirection[1] == 0xcdcdcdcd, "got rglDirection[1] %d expected %d\n",
6386 desc.rglDirection[1], 0xcdcdcdcd );
6387 ok( desc.rglDirection[2] == 0xcdcdcdcd, "got rglDirection[2] %d expected %d\n",
6388 desc.rglDirection[2], 0xcdcdcdcd );
6390 else
6392 ok( desc.rglDirection[0] == 6343, "got rglDirection[0] %d expected %d\n",
6393 desc.rglDirection[0], 6343 );
6394 if (i == 2)
6396 ok( desc.rglDirection[1] == 0, "got rglDirection[1] %d expected %d\n",
6397 desc.rglDirection[1], 0 );
6398 ok( desc.rglDirection[2] == 0xcdcdcdcd, "got rglDirection[2] %d expected %d\n",
6399 desc.rglDirection[2], 0xcdcdcdcd );
6401 else
6403 ok( desc.rglDirection[1] == 5330, "got rglDirection[1] %d expected %d\n",
6404 desc.rglDirection[1], 5330 );
6405 ok( desc.rglDirection[2] == 0, "got rglDirection[2] %d expected %d\n",
6406 desc.rglDirection[2], 0 );
6410 desc.dwFlags = DIEFF_CARTESIAN;
6411 desc.cAxes = i;
6412 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
6413 ok( hr == DI_OK, "GetParameters returned %#x\n", hr );
6414 desc.cAxes = 3;
6415 memset( desc.rglDirection, 0xcd, 3 * sizeof(LONG) );
6416 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
6417 ok( hr == DI_OK, "GetParameters returned %#x\n", hr );
6418 ok( desc.cAxes == i, "got cAxes %u expected 2\n", desc.cAxes );
6419 ok( desc.rglDirection[0] == 1000, "got rglDirection[0] %d expected %d\n", desc.rglDirection[0], 1000 );
6420 if (i == 1)
6421 ok( desc.rglDirection[1] == 0xcdcdcdcd, "got rglDirection[1] %d expected %d\n",
6422 desc.rglDirection[1], 0xcdcdcdcd );
6423 else
6424 ok( desc.rglDirection[1] == 2000, "got rglDirection[1] %d expected %d\n",
6425 desc.rglDirection[1], 2000 );
6426 if (i <= 2)
6427 ok( desc.rglDirection[2] == 0xcdcdcdcd, "got rglDirection[2] %d expected %d\n",
6428 desc.rglDirection[2], 0xcdcdcdcd );
6429 else
6430 ok( desc.rglDirection[2] == 3000, "got rglDirection[2] %d expected %d\n",
6431 desc.rglDirection[2], 3000 );
6433 desc.dwFlags = DIEFF_POLAR;
6434 desc.cAxes = 1;
6435 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
6436 if (i != 2) ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#x\n", hr );
6437 else ok( hr == DIERR_MOREDATA, "GetParameters returned %#x\n", hr );
6438 desc.cAxes = 3;
6439 memset( desc.rglDirection, 0xcd, 3 * sizeof(LONG) );
6440 hr = IDirectInputEffect_GetParameters( effect, &desc, DIEP_DIRECTION );
6441 if (i != 2) ok( hr == DIERR_INVALIDPARAM, "GetParameters returned %#x\n", hr );
6442 else
6444 ok( hr == DI_OK, "GetParameters returned %#x\n", hr );
6445 ok( desc.cAxes == i, "got cAxes %u expected 2\n", desc.cAxes );
6446 ok( desc.rglDirection[0] == 15343, "got rglDirection[0] %d expected %d\n",
6447 desc.rglDirection[0], 15343 );
6448 ok( desc.rglDirection[1] == 0, "got rglDirection[1] %d expected %d\n", desc.rglDirection[1], 0 );
6449 ok( desc.rglDirection[2] == 0xcdcdcdcd, "got rglDirection[2] %d expected %d\n",
6450 desc.rglDirection[2], 0xcdcdcdcd );
6453 ref = IDirectInputEffect_Release( effect );
6454 ok( ref == 0, "Release returned %d\n", ref );
6455 winetest_pop_context();
6458 hr = IDirectInputDevice8_CreateEffect( device, &GUID_Sine, NULL, &effect, NULL );
6459 ok( hr == DI_OK, "CreateEffect returned %#x\n", hr );
6461 set_hid_expect( file, expect_download_2, sizeof(expect_download_2) );
6462 flags = version >= 0x700 ? DIEP_ALLPARAMS : DIEP_ALLPARAMS_DX5;
6463 hr = IDirectInputEffect_SetParameters( effect, &expect_desc, flags );
6464 ok( hr == DI_OK, "SetParameters returned %#x\n", hr );
6465 set_hid_expect( file, NULL, 0 );
6466 desc = expect_desc;
6467 desc.dwDuration = INFINITE;
6468 desc.dwTriggerButton = DIDFT_PSHBUTTON | DIDFT_MAKEINSTANCE( 0 ) | DIDFT_FFEFFECTTRIGGER,
6469 hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_NODOWNLOAD|DIEP_DURATION|DIEP_TRIGGERBUTTON );
6470 ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#x\n", hr );
6471 set_hid_expect( file, expect_update, sizeof(expect_update) );
6472 hr = IDirectInputEffect_SetParameters( effect, &expect_desc, 0 );
6473 ok( hr == DI_OK, "SetParameters returned %#x\n", hr );
6474 wait_hid_expect( file, 100 ); /* these updates are sent asynchronously */
6475 desc = expect_desc;
6476 desc.dwDuration = INFINITE;
6477 desc.dwTriggerButton = DIDFT_PSHBUTTON | DIDFT_MAKEINSTANCE( 0 ) | DIDFT_FFEFFECTTRIGGER,
6478 hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_NODOWNLOAD|DIEP_DURATION|DIEP_TRIGGERBUTTON );
6479 ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#x\n", hr );
6480 set_hid_expect( file, expect_update, sizeof(expect_update) );
6481 hr = IDirectInputEffect_SetParameters( effect, &expect_desc, 0 );
6482 ok( hr == DI_OK, "SetParameters returned %#x\n", hr );
6483 wait_hid_expect( file, 100 ); /* these updates are sent asynchronously */
6485 desc = expect_desc;
6486 desc.lpEnvelope = &envelope;
6487 desc.lpEnvelope->dwAttackTime = 1000;
6488 hr = IDirectInputEffect_SetParameters( effect, &desc, DIEP_NODOWNLOAD|DIEP_ENVELOPE );
6489 ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#x\n", hr );
6490 set_hid_expect( file, expect_set_envelope, sizeof(expect_set_envelope) );
6491 hr = IDirectInputEffect_SetParameters( effect, &expect_desc, 0 );
6492 ok( hr == DI_OK, "SetParameters returned %#x\n", hr );
6493 wait_hid_expect( file, 100 ); /* these updates are sent asynchronously */
6495 set_hid_expect( file, &expect_stop, sizeof(expect_stop) );
6496 ref = IDirectInputEffect_Release( effect );
6497 ok( ref == 0, "Release returned %d\n", ref );
6498 set_hid_expect( file, NULL, 0 );
6500 set_hid_expect( file, expect_reset, sizeof(expect_reset) );
6501 hr = IDirectInputDevice8_Unacquire( device );
6502 ok( hr == DI_OK, "Acquire returned: %#x\n", hr );
6503 set_hid_expect( file, NULL, 0 );
6504 hr = IDirectInputDevice8_CreateEffect( device, &GUID_Sine, &expect_desc, &effect, NULL );
6505 ok( hr == DI_OK, "CreateEffect returned %#x\n", hr );
6506 ref = IDirectInputEffect_Release( effect );
6507 ok( ref == 0, "Release returned %d\n", ref );
6508 set_hid_expect( file, expect_acquire, sizeof(expect_acquire) );
6509 hr = IDirectInputDevice8_Acquire( device );
6510 ok( hr == DI_OK, "Acquire returned: %#x\n", hr );
6511 wait_hid_expect( file, 100 ); /* device gain reports are written asynchronously */
6514 static void test_condition_effect( IDirectInputDevice8W *device, HANDLE file, DWORD version )
6516 struct hid_expect expect_create[] =
6518 /* set condition */
6520 .code = IOCTL_HID_WRITE_REPORT,
6521 .report_id = 7,
6522 .report_len = 8,
6523 .report_buf = {0x07,0x00,0xf9,0x19,0xd9,0xff,0xff,0x99},
6525 /* set condition */
6527 .code = IOCTL_HID_WRITE_REPORT,
6528 .report_id = 7,
6529 .report_len = 8,
6530 .report_buf = {0x07,0x00,0x4c,0x3f,0xcc,0x4c,0x33,0x19},
6532 /* update effect */
6534 .code = IOCTL_HID_WRITE_REPORT,
6535 .report_id = 3,
6536 .report_len = 11,
6537 .report_buf = {0x03,0x01,0x03,0x08,0x01,0x00,version >= 0x700 ? 0x06 : 0x00,0x00,0x01,0x55,0x00},
6540 struct hid_expect expect_create_1[] =
6542 /* set condition */
6544 .code = IOCTL_HID_WRITE_REPORT,
6545 .report_id = 7,
6546 .report_len = 8,
6547 .report_buf = {0x07,0x00,0x4c,0x3f,0xcc,0x4c,0x33,0x19},
6549 /* update effect */
6551 .code = IOCTL_HID_WRITE_REPORT,
6552 .report_id = 3,
6553 .report_len = 11,
6554 .report_buf = {0x03,0x01,0x03,0x08,0x01,0x00,version >= 0x700 ? 0x06 : 0x00,0x00,0x01,0x3f,0x00},
6557 struct hid_expect expect_create_2[] =
6559 /* set condition */
6561 .code = IOCTL_HID_WRITE_REPORT,
6562 .report_id = 7,
6563 .report_len = 8,
6564 .report_buf = {0x07,0x00,0x4c,0x3f,0xcc,0x4c,0x33,0x19},
6566 /* update effect */
6568 .code = IOCTL_HID_WRITE_REPORT,
6569 .report_id = 3,
6570 .report_len = 11,
6571 .report_buf = {0x03,0x01,0x03,0x08,0x01,0x00,version >= 0x700 ? 0x06 : 0x00,0x00,0x01,0x55,0xf1},
6574 struct hid_expect expect_create_3[] =
6576 /* set condition */
6578 .code = IOCTL_HID_WRITE_REPORT,
6579 .report_id = 7,
6580 .report_len = 8,
6581 .report_buf = {0x07,0x00,0x4c,0x3f,0xcc,0x4c,0x33,0x19},
6583 /* update effect */
6585 .code = IOCTL_HID_WRITE_REPORT,
6586 .report_id = 3,
6587 .report_len = 11,
6588 .report_buf = {0x03,0x01,0x03,0x08,0x01,0x00,version >= 0x700 ? 0x06 : 0x00,0x00,0x01,0x55,0x00},
6591 struct hid_expect expect_destroy =
6593 .code = IOCTL_HID_WRITE_REPORT,
6594 .report_id = 2,
6595 .report_len = 4,
6596 .report_buf = {0x02, 0x01, 0x03, 0x00},
6598 static const DWORD expect_axes[3] =
6600 DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 0 ) | DIDFT_FFACTUATOR,
6601 DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 2 ) | DIDFT_FFACTUATOR,
6602 DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 1 ) | DIDFT_FFACTUATOR,
6604 static const LONG expect_directions[3] = {
6605 +3000,
6609 static const DIENVELOPE expect_envelope =
6611 .dwSize = sizeof(DIENVELOPE),
6612 .dwAttackLevel = 1000,
6613 .dwAttackTime = 2000,
6614 .dwFadeLevel = 3000,
6615 .dwFadeTime = 4000,
6617 static const DICONDITION expect_condition[3] =
6620 .lOffset = -500,
6621 .lPositiveCoefficient = 2000,
6622 .lNegativeCoefficient = -3000,
6623 .dwPositiveSaturation = -4000,
6624 .dwNegativeSaturation = -5000,
6625 .lDeadBand = 6000,
6628 .lOffset = 6000,
6629 .lPositiveCoefficient = 5000,
6630 .lNegativeCoefficient = -4000,
6631 .dwPositiveSaturation = 3000,
6632 .dwNegativeSaturation = 2000,
6633 .lDeadBand = 1000,
6636 .lOffset = -7000,
6637 .lPositiveCoefficient = -8000,
6638 .lNegativeCoefficient = 9000,
6639 .dwPositiveSaturation = 10000,
6640 .dwNegativeSaturation = 11000,
6641 .lDeadBand = -12000,
6644 const DIEFFECT expect_desc =
6646 .dwSize = version >= 0x700 ? sizeof(DIEFFECT_DX6) : sizeof(DIEFFECT_DX5),
6647 .dwFlags = DIEFF_SPHERICAL | DIEFF_OBJECTIDS,
6648 .dwDuration = 1000,
6649 .dwSamplePeriod = 2000,
6650 .dwGain = 3000,
6651 .dwTriggerButton = DIDFT_PSHBUTTON | DIDFT_MAKEINSTANCE( 0 ) | DIDFT_FFEFFECTTRIGGER,
6652 .dwTriggerRepeatInterval = 5000,
6653 .cAxes = 2,
6654 .rgdwAxes = (void *)expect_axes,
6655 .rglDirection = (void *)expect_directions,
6656 .lpEnvelope = (void *)&expect_envelope,
6657 .cbTypeSpecificParams = 2 * sizeof(DICONDITION),
6658 .lpvTypeSpecificParams = (void *)expect_condition,
6659 .dwStartDelay = 6000,
6661 struct check_created_effect_params check_params = {0};
6662 DIENVELOPE envelope =
6663 {.dwSize = sizeof(DIENVELOPE)};
6664 DICONDITION condition[2] = {0};
6665 IDirectInputEffect *effect;
6666 LONG directions[4] = {0};
6667 DWORD axes[4] = {0};
6668 DIEFFECT desc =
6670 .dwSize = version >= 0x700 ? sizeof(DIEFFECT_DX6) : sizeof(DIEFFECT_DX5),
6671 .dwFlags = DIEFF_SPHERICAL | DIEFF_OBJECTIDS,
6672 .cAxes = 4,
6673 .rgdwAxes = axes,
6674 .rglDirection = directions,
6675 .lpEnvelope = &envelope,
6676 .cbTypeSpecificParams = 2 * sizeof(DICONDITION),
6677 .lpvTypeSpecificParams = condition,
6679 HRESULT hr;
6680 ULONG ref;
6681 GUID guid;
6683 set_hid_expect( file, expect_create, sizeof(expect_create) );
6684 hr = IDirectInputDevice8_CreateEffect( device, &GUID_Spring, &expect_desc, &effect, NULL );
6685 ok( hr == DI_OK, "CreateEffect returned %#x\n", hr );
6686 set_hid_expect( file, NULL, 0 );
6688 check_params.expect_effect = effect;
6689 hr = IDirectInputDevice8_EnumCreatedEffectObjects( device, check_created_effect_objects, &check_params, 0 );
6690 ok( hr == DI_OK, "EnumCreatedEffectObjects returned %#x\n", hr );
6691 ok( check_params.count == 1, "got count %u, expected 1\n", check_params.count );
6693 hr = IDirectInputEffect_GetEffectGuid( effect, &guid );
6694 ok( hr == DI_OK, "GetEffectGuid returned %#x\n", hr );
6695 ok( IsEqualGUID( &guid, &GUID_Spring ), "got guid %s, expected %s\n", debugstr_guid( &guid ),
6696 debugstr_guid( &GUID_Spring ) );
6698 hr = IDirectInputEffect_GetParameters( effect, &desc, version >= 0x700 ? DIEP_ALLPARAMS : DIEP_ALLPARAMS_DX5 );
6699 ok( hr == DI_OK, "GetParameters returned %#x\n", hr );
6700 check_member( desc, expect_desc, "%u", dwDuration );
6701 check_member( desc, expect_desc, "%u", dwSamplePeriod );
6702 check_member( desc, expect_desc, "%u", dwGain );
6703 check_member( desc, expect_desc, "%#x", dwTriggerButton );
6704 check_member( desc, expect_desc, "%u", dwTriggerRepeatInterval );
6705 check_member( desc, expect_desc, "%u", cAxes );
6706 check_member( desc, expect_desc, "%#x", rgdwAxes[0] );
6707 check_member( desc, expect_desc, "%#x", rgdwAxes[1] );
6708 check_member( desc, expect_desc, "%d", rglDirection[0] );
6709 check_member( desc, expect_desc, "%d", rglDirection[1] );
6710 check_member( desc, expect_desc, "%u", cbTypeSpecificParams );
6711 if (version >= 0x700) check_member( desc, expect_desc, "%u", dwStartDelay );
6712 else ok( desc.dwStartDelay == 0, "got dwStartDelay %#x\n", desc.dwStartDelay );
6713 check_member( envelope, expect_envelope, "%u", dwAttackLevel );
6714 check_member( envelope, expect_envelope, "%u", dwAttackTime );
6715 check_member( envelope, expect_envelope, "%u", dwFadeLevel );
6716 check_member( envelope, expect_envelope, "%u", dwFadeTime );
6717 check_member( condition[0], expect_condition[0], "%d", lOffset );
6718 check_member( condition[0], expect_condition[0], "%d", lPositiveCoefficient );
6719 check_member( condition[0], expect_condition[0], "%d", lNegativeCoefficient );
6720 check_member( condition[0], expect_condition[0], "%u", dwPositiveSaturation );
6721 check_member( condition[0], expect_condition[0], "%u", dwNegativeSaturation );
6722 check_member( condition[0], expect_condition[0], "%d", lDeadBand );
6723 check_member( condition[1], expect_condition[1], "%d", lOffset );
6724 check_member( condition[1], expect_condition[1], "%d", lPositiveCoefficient );
6725 check_member( condition[1], expect_condition[1], "%d", lNegativeCoefficient );
6726 check_member( condition[1], expect_condition[1], "%u", dwPositiveSaturation );
6727 check_member( condition[1], expect_condition[1], "%u", dwNegativeSaturation );
6728 check_member( condition[1], expect_condition[1], "%d", lDeadBand );
6730 set_hid_expect( file, &expect_destroy, sizeof(expect_destroy) );
6731 ref = IDirectInputEffect_Release( effect );
6732 ok( ref == 0, "Release returned %d\n", ref );
6733 set_hid_expect( file, NULL, 0 );
6735 desc = expect_desc;
6736 desc.cAxes = 1;
6737 hr = IDirectInputDevice8_CreateEffect( device, &GUID_Spring, &desc, &effect, NULL );
6738 ok( hr == DIERR_INVALIDPARAM, "CreateEffect returned %#x\n", hr );
6739 desc.cbTypeSpecificParams = 1 * sizeof(DICONDITION);
6740 desc.lpvTypeSpecificParams = (void *)&expect_condition[1];
6741 set_hid_expect( file, expect_create_1, sizeof(expect_create_1) );
6742 hr = IDirectInputDevice8_CreateEffect( device, &GUID_Spring, &desc, &effect, NULL );
6743 ok( hr == DI_OK, "CreateEffect returned %#x\n", hr );
6744 set_hid_expect( file, NULL, 0 );
6746 set_hid_expect( file, &expect_destroy, sizeof(expect_destroy) );
6747 ref = IDirectInputEffect_Release( effect );
6748 ok( ref == 0, "Release returned %d\n", ref );
6749 set_hid_expect( file, NULL, 0 );
6751 desc = expect_desc;
6752 desc.cAxes = 3;
6753 desc.rglDirection = directions;
6754 desc.rglDirection[0] = +3000;
6755 desc.rglDirection[1] = -2000;
6756 desc.rglDirection[2] = +1000;
6757 desc.cbTypeSpecificParams = 1 * sizeof(DICONDITION);
6758 desc.lpvTypeSpecificParams = (void *)&expect_condition[1];
6759 set_hid_expect( file, expect_create_2, sizeof(expect_create_2) );
6760 hr = IDirectInputDevice8_CreateEffect( device, &GUID_Spring, &desc, &effect, NULL );
6761 ok( hr == DI_OK, "CreateEffect returned %#x\n", hr );
6762 set_hid_expect( file, NULL, 0 );
6764 set_hid_expect( file, &expect_destroy, sizeof(expect_destroy) );
6765 ref = IDirectInputEffect_Release( effect );
6766 ok( ref == 0, "Release returned %d\n", ref );
6767 set_hid_expect( file, NULL, 0 );
6769 desc = expect_desc;
6770 desc.cAxes = 2;
6771 desc.rgdwAxes = axes;
6772 desc.rgdwAxes[0] = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 1 ) | DIDFT_FFACTUATOR;
6773 desc.rgdwAxes[1] = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 2 ) | DIDFT_FFACTUATOR;
6774 desc.rglDirection = directions;
6775 desc.rglDirection[0] = +3000;
6776 desc.rglDirection[1] = -2000;
6777 desc.cbTypeSpecificParams = 1 * sizeof(DICONDITION);
6778 desc.lpvTypeSpecificParams = (void *)&expect_condition[1];
6779 set_hid_expect( file, expect_create_3, sizeof(expect_create_3) );
6780 hr = IDirectInputDevice8_CreateEffect( device, &GUID_Spring, &desc, &effect, NULL );
6781 ok( hr == DI_OK, "CreateEffect returned %#x\n", hr );
6782 set_hid_expect( file, NULL, 0 );
6784 set_hid_expect( file, &expect_destroy, sizeof(expect_destroy) );
6785 ref = IDirectInputEffect_Release( effect );
6786 ok( ref == 0, "Release returned %d\n", ref );
6787 set_hid_expect( file, NULL, 0 );
6790 static void test_force_feedback_joystick( DWORD version )
6792 #include "psh_hid_macros.h"
6793 const unsigned char report_descriptor[] = {
6794 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
6795 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
6796 COLLECTION(1, Application),
6797 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
6798 COLLECTION(1, Report),
6799 REPORT_ID(1, 1),
6801 USAGE(1, HID_USAGE_GENERIC_X),
6802 USAGE(1, HID_USAGE_GENERIC_Y),
6803 USAGE(1, HID_USAGE_GENERIC_Z),
6804 LOGICAL_MINIMUM(1, 0),
6805 LOGICAL_MAXIMUM(1, 0x7f),
6806 PHYSICAL_MINIMUM(1, 0),
6807 PHYSICAL_MAXIMUM(1, 0x7f),
6808 REPORT_SIZE(1, 8),
6809 REPORT_COUNT(1, 3),
6810 INPUT(1, Data|Var|Abs),
6812 USAGE_PAGE(1, HID_USAGE_PAGE_BUTTON),
6813 USAGE_MINIMUM(1, 1),
6814 USAGE_MAXIMUM(1, 2),
6815 LOGICAL_MINIMUM(1, 0),
6816 LOGICAL_MAXIMUM(1, 1),
6817 PHYSICAL_MINIMUM(1, 0),
6818 PHYSICAL_MAXIMUM(1, 1),
6819 REPORT_SIZE(1, 1),
6820 REPORT_COUNT(1, 2),
6821 INPUT(1, Data|Var|Abs),
6822 REPORT_COUNT(1, 6),
6823 INPUT(1, Cnst|Var|Abs),
6824 END_COLLECTION,
6826 USAGE_PAGE(1, HID_USAGE_PAGE_PID),
6827 USAGE(1, PID_USAGE_STATE_REPORT),
6828 COLLECTION(1, Report),
6829 REPORT_ID(1, 2),
6831 USAGE(1, PID_USAGE_DEVICE_PAUSED),
6832 USAGE(1, PID_USAGE_ACTUATORS_ENABLED),
6833 USAGE(1, PID_USAGE_SAFETY_SWITCH),
6834 USAGE(1, PID_USAGE_ACTUATOR_OVERRIDE_SWITCH),
6835 USAGE(1, PID_USAGE_ACTUATOR_POWER),
6836 LOGICAL_MINIMUM(1, 0),
6837 LOGICAL_MAXIMUM(1, 1),
6838 PHYSICAL_MINIMUM(1, 0),
6839 PHYSICAL_MAXIMUM(1, 1),
6840 REPORT_SIZE(1, 1),
6841 REPORT_COUNT(1, 5),
6842 INPUT(1, Data|Var|Abs),
6843 REPORT_COUNT(1, 3),
6844 INPUT(1, Cnst|Var|Abs),
6846 USAGE(1, PID_USAGE_EFFECT_PLAYING),
6847 LOGICAL_MINIMUM(1, 0),
6848 LOGICAL_MAXIMUM(1, 1),
6849 PHYSICAL_MINIMUM(1, 0),
6850 PHYSICAL_MAXIMUM(1, 1),
6851 REPORT_SIZE(1, 1),
6852 REPORT_COUNT(1, 1),
6853 INPUT(1, Data|Var|Abs),
6855 USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX),
6856 LOGICAL_MAXIMUM(1, 0x7f),
6857 LOGICAL_MINIMUM(1, 0x00),
6858 REPORT_SIZE(1, 7),
6859 REPORT_COUNT(1, 1),
6860 INPUT(1, Data|Var|Abs),
6861 END_COLLECTION,
6863 USAGE_PAGE(1, HID_USAGE_PAGE_PID),
6864 USAGE(1, PID_USAGE_DEVICE_CONTROL_REPORT),
6865 COLLECTION(1, Report),
6866 REPORT_ID(1, 1),
6868 USAGE(1, PID_USAGE_DEVICE_CONTROL),
6869 COLLECTION(1, Logical),
6870 USAGE(1, PID_USAGE_DC_DEVICE_RESET),
6871 LOGICAL_MINIMUM(1, 1),
6872 LOGICAL_MAXIMUM(1, 2),
6873 PHYSICAL_MINIMUM(1, 1),
6874 PHYSICAL_MAXIMUM(1, 2),
6875 REPORT_SIZE(1, 8),
6876 REPORT_COUNT(1, 1),
6877 OUTPUT(1, Data|Ary|Abs),
6878 END_COLLECTION,
6879 END_COLLECTION,
6881 USAGE(1, PID_USAGE_EFFECT_OPERATION_REPORT),
6882 COLLECTION(1, Report),
6883 REPORT_ID(1, 2),
6885 USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX),
6886 LOGICAL_MINIMUM(1, 0),
6887 LOGICAL_MAXIMUM(1, 0x7f),
6888 PHYSICAL_MINIMUM(1, 0),
6889 PHYSICAL_MAXIMUM(1, 0x7f),
6890 REPORT_SIZE(1, 8),
6891 REPORT_COUNT(1, 1),
6892 OUTPUT(1, Data|Var|Abs),
6894 USAGE(1, PID_USAGE_EFFECT_OPERATION),
6895 COLLECTION(1, NamedArray),
6896 USAGE(1, PID_USAGE_OP_EFFECT_START),
6897 USAGE(1, PID_USAGE_OP_EFFECT_START_SOLO),
6898 USAGE(1, PID_USAGE_OP_EFFECT_STOP),
6899 LOGICAL_MINIMUM(1, 1),
6900 LOGICAL_MAXIMUM(1, 3),
6901 PHYSICAL_MINIMUM(1, 1),
6902 PHYSICAL_MAXIMUM(1, 3),
6903 REPORT_SIZE(1, 8),
6904 REPORT_COUNT(1, 1),
6905 OUTPUT(1, Data|Ary|Abs),
6906 END_COLLECTION,
6908 USAGE(1, PID_USAGE_LOOP_COUNT),
6909 LOGICAL_MINIMUM(1, 0),
6910 LOGICAL_MAXIMUM(1, 0x7f),
6911 PHYSICAL_MINIMUM(1, 0),
6912 PHYSICAL_MAXIMUM(1, 0x7f),
6913 REPORT_SIZE(1, 8),
6914 REPORT_COUNT(1, 1),
6915 OUTPUT(1, Data|Var|Abs),
6916 END_COLLECTION,
6918 USAGE(1, PID_USAGE_SET_EFFECT_REPORT),
6919 COLLECTION(1, Report),
6920 REPORT_ID(1, 3),
6922 USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX),
6923 LOGICAL_MINIMUM(1, 0),
6924 LOGICAL_MAXIMUM(1, 0x7f),
6925 PHYSICAL_MINIMUM(1, 0),
6926 PHYSICAL_MAXIMUM(1, 0x7f),
6927 REPORT_SIZE(1, 8),
6928 REPORT_COUNT(1, 1),
6929 OUTPUT(1, Data|Var|Abs),
6931 USAGE(1, PID_USAGE_EFFECT_TYPE),
6932 COLLECTION(1, NamedArray),
6933 USAGE(1, PID_USAGE_ET_SQUARE),
6934 USAGE(1, PID_USAGE_ET_SINE),
6935 USAGE(1, PID_USAGE_ET_SPRING),
6936 LOGICAL_MINIMUM(1, 1),
6937 LOGICAL_MAXIMUM(1, 3),
6938 PHYSICAL_MINIMUM(1, 1),
6939 PHYSICAL_MAXIMUM(1, 3),
6940 REPORT_SIZE(1, 8),
6941 REPORT_COUNT(1, 1),
6942 OUTPUT(1, Data|Ary|Abs),
6943 END_COLLECTION,
6945 USAGE(1, PID_USAGE_AXES_ENABLE),
6946 COLLECTION(1, Logical),
6947 USAGE(4, (HID_USAGE_PAGE_GENERIC << 16)|HID_USAGE_GENERIC_X),
6948 USAGE(4, (HID_USAGE_PAGE_GENERIC << 16)|HID_USAGE_GENERIC_Y),
6949 USAGE(4, (HID_USAGE_PAGE_GENERIC << 16)|HID_USAGE_GENERIC_Z),
6950 LOGICAL_MINIMUM(1, 0),
6951 LOGICAL_MAXIMUM(1, 1),
6952 PHYSICAL_MINIMUM(1, 0),
6953 PHYSICAL_MAXIMUM(1, 1),
6954 REPORT_SIZE(1, 1),
6955 REPORT_COUNT(1, 3),
6956 OUTPUT(1, Data|Var|Abs),
6957 END_COLLECTION,
6958 USAGE(1, PID_USAGE_DIRECTION_ENABLE),
6959 REPORT_COUNT(1, 1),
6960 OUTPUT(1, Data|Var|Abs),
6961 REPORT_COUNT(1, 4),
6962 OUTPUT(1, Cnst|Var|Abs),
6964 USAGE(1, PID_USAGE_DURATION),
6965 USAGE(1, PID_USAGE_START_DELAY),
6966 UNIT(2, 0x1003), /* Eng Lin:Time */
6967 UNIT_EXPONENT(1, -3), /* 10^-3 */
6968 LOGICAL_MINIMUM(1, 0),
6969 LOGICAL_MAXIMUM(2, 0x7fff),
6970 PHYSICAL_MINIMUM(1, 0),
6971 PHYSICAL_MAXIMUM(2, 0x7fff),
6972 REPORT_SIZE(1, 16),
6973 REPORT_COUNT(1, 2),
6974 OUTPUT(1, Data|Var|Abs),
6975 UNIT(1, 0),
6976 UNIT_EXPONENT(1, 0),
6978 USAGE(1, PID_USAGE_TRIGGER_BUTTON),
6979 LOGICAL_MINIMUM(1, 1),
6980 LOGICAL_MAXIMUM(1, 0x08),
6981 PHYSICAL_MINIMUM(1, 1),
6982 PHYSICAL_MAXIMUM(1, 0x08),
6983 REPORT_SIZE(1, 8),
6984 REPORT_COUNT(1, 1),
6985 OUTPUT(1, Data|Var|Abs),
6987 USAGE(1, PID_USAGE_DIRECTION),
6988 COLLECTION(1, Logical),
6989 USAGE(4, (HID_USAGE_PAGE_ORDINAL << 16)|1),
6990 USAGE(4, (HID_USAGE_PAGE_ORDINAL << 16)|2),
6991 UNIT(1, 0x14), /* Eng Rot:Angular Pos */
6992 UNIT_EXPONENT(1, -2), /* 10^-2 */
6993 LOGICAL_MINIMUM(1, 0),
6994 LOGICAL_MAXIMUM(2, 0x00ff),
6995 PHYSICAL_MINIMUM(1, 0),
6996 PHYSICAL_MAXIMUM(4, 0x00008ca0),
6997 UNIT(1, 0),
6998 REPORT_SIZE(1, 8),
6999 REPORT_COUNT(1, 2),
7000 OUTPUT(1, Data|Var|Abs),
7001 UNIT_EXPONENT(1, 0),
7002 UNIT(1, 0),
7003 END_COLLECTION,
7004 END_COLLECTION,
7006 USAGE(1, PID_USAGE_SET_PERIODIC_REPORT),
7007 COLLECTION(1, Logical),
7008 REPORT_ID(1, 5),
7010 USAGE(1, PID_USAGE_MAGNITUDE),
7011 LOGICAL_MINIMUM(1, 0),
7012 LOGICAL_MAXIMUM(2, 0x00ff),
7013 PHYSICAL_MINIMUM(1, 0),
7014 PHYSICAL_MAXIMUM(2, 0x2710),
7015 REPORT_SIZE(1, 8),
7016 REPORT_COUNT(1, 1),
7017 OUTPUT(1, Data|Var|Abs),
7018 END_COLLECTION,
7020 USAGE(1, PID_USAGE_SET_ENVELOPE_REPORT),
7021 COLLECTION(1, Logical),
7022 REPORT_ID(1, 6),
7024 USAGE(1, PID_USAGE_ATTACK_LEVEL),
7025 USAGE(1, PID_USAGE_FADE_LEVEL),
7026 LOGICAL_MINIMUM(1, 0),
7027 LOGICAL_MAXIMUM(2, 0x00ff),
7028 PHYSICAL_MINIMUM(1, 0),
7029 PHYSICAL_MAXIMUM(2, 0x2710),
7030 REPORT_SIZE(1, 8),
7031 REPORT_COUNT(1, 2),
7032 OUTPUT(1, Data|Var|Abs),
7034 USAGE(1, PID_USAGE_ATTACK_TIME),
7035 USAGE(1, PID_USAGE_FADE_TIME),
7036 UNIT(2, 0x1003), /* Eng Lin:Time */
7037 UNIT_EXPONENT(1, -3), /* 10^-3 */
7038 LOGICAL_MINIMUM(1, 0),
7039 LOGICAL_MAXIMUM(2, 0x7fff),
7040 PHYSICAL_MINIMUM(1, 0),
7041 PHYSICAL_MAXIMUM(2, 0x7fff),
7042 REPORT_SIZE(1, 16),
7043 REPORT_COUNT(1, 2),
7044 OUTPUT(1, Data|Var|Abs),
7045 PHYSICAL_MAXIMUM(1, 0),
7046 UNIT_EXPONENT(1, 0),
7047 UNIT(1, 0),
7048 END_COLLECTION,
7051 USAGE(1, PID_USAGE_SET_CONDITION_REPORT),
7052 COLLECTION(1, Logical),
7053 REPORT_ID(1, 7),
7055 USAGE(1, PID_USAGE_TYPE_SPECIFIC_BLOCK_OFFSET),
7056 COLLECTION(1, Logical),
7057 USAGE(4, (HID_USAGE_PAGE_ORDINAL << 16)|1),
7058 USAGE(4, (HID_USAGE_PAGE_ORDINAL << 16)|2),
7059 LOGICAL_MINIMUM(1, 0),
7060 LOGICAL_MAXIMUM(1, 1),
7061 PHYSICAL_MINIMUM(1, 0),
7062 PHYSICAL_MAXIMUM(1, 1),
7063 REPORT_SIZE(1, 2),
7064 REPORT_COUNT(1, 2),
7065 OUTPUT(1, Data|Var|Abs),
7066 END_COLLECTION,
7067 REPORT_SIZE(1, 4),
7068 REPORT_COUNT(1, 1),
7069 OUTPUT(1, Cnst|Var|Abs),
7071 USAGE(1, PID_USAGE_CP_OFFSET),
7072 LOGICAL_MINIMUM(1, 0x80),
7073 LOGICAL_MAXIMUM(1, 0x7f),
7074 PHYSICAL_MINIMUM(2, 0xd8f0),
7075 PHYSICAL_MAXIMUM(2, 0x2710),
7076 REPORT_SIZE(1, 8),
7077 REPORT_COUNT(1, 1),
7078 OUTPUT(1, Data|Var|Abs),
7080 USAGE(1, PID_USAGE_POSITIVE_COEFFICIENT),
7081 USAGE(1, PID_USAGE_NEGATIVE_COEFFICIENT),
7082 LOGICAL_MINIMUM(1, 0x80),
7083 LOGICAL_MAXIMUM(1, 0x7f),
7084 PHYSICAL_MINIMUM(2, 0xd8f0),
7085 PHYSICAL_MAXIMUM(2, 0x2710),
7086 REPORT_SIZE(1, 8),
7087 REPORT_COUNT(1, 2),
7088 OUTPUT(1, Data|Var|Abs),
7090 USAGE(1, PID_USAGE_POSITIVE_SATURATION),
7091 USAGE(1, PID_USAGE_NEGATIVE_SATURATION),
7092 LOGICAL_MINIMUM(1, 0),
7093 LOGICAL_MAXIMUM(2, 0x00ff),
7094 PHYSICAL_MINIMUM(1, 0),
7095 PHYSICAL_MAXIMUM(2, 0x2710),
7096 REPORT_SIZE(1, 8),
7097 REPORT_COUNT(1, 2),
7098 OUTPUT(1, Data|Var|Abs),
7100 USAGE(1, PID_USAGE_DEAD_BAND),
7101 LOGICAL_MINIMUM(1, 0),
7102 LOGICAL_MAXIMUM(2, 0x00ff),
7103 PHYSICAL_MINIMUM(1, 0),
7104 PHYSICAL_MAXIMUM(2, 0x2710),
7105 REPORT_SIZE(1, 8),
7106 REPORT_COUNT(1, 1),
7107 OUTPUT(1, Data|Var|Abs),
7108 END_COLLECTION,
7111 USAGE(1, PID_USAGE_DEVICE_GAIN_REPORT),
7112 COLLECTION(1, Logical),
7113 REPORT_ID(1, 8),
7115 USAGE(1, PID_USAGE_DEVICE_GAIN),
7116 LOGICAL_MINIMUM(1, 0),
7117 LOGICAL_MAXIMUM(2, 0x00ff),
7118 PHYSICAL_MINIMUM(1, 0),
7119 PHYSICAL_MAXIMUM(2, 0x2710),
7120 REPORT_SIZE(1, 8),
7121 REPORT_COUNT(1, 1),
7122 OUTPUT(1, Data|Var|Abs),
7123 END_COLLECTION,
7124 END_COLLECTION,
7126 #undef REPORT_ID_OR_USAGE_PAGE
7127 #include "pop_hid_macros.h"
7129 static const HIDP_CAPS hid_caps =
7131 .InputReportByteLength = 5,
7133 const DIDEVCAPS expect_caps =
7135 .dwSize = sizeof(DIDEVCAPS),
7136 .dwFlags = DIDC_FORCEFEEDBACK | DIDC_ATTACHED | DIDC_EMULATED | DIDC_STARTDELAY |
7137 DIDC_FFFADE | DIDC_FFATTACK | DIDC_DEADBAND | DIDC_SATURATION,
7138 .dwDevType = version >= 0x800 ? DIDEVTYPE_HID | (DI8DEVTYPEJOYSTICK_LIMITED << 8) | DI8DEVTYPE_JOYSTICK
7139 : DIDEVTYPE_HID | (DIDEVTYPEJOYSTICK_UNKNOWN << 8) | DIDEVTYPE_JOYSTICK,
7140 .dwAxes = 3,
7141 .dwButtons = 2,
7142 .dwFFSamplePeriod = 1000000,
7143 .dwFFMinTimeResolution = 1000000,
7144 .dwHardwareRevision = 1,
7145 .dwFFDriverVersion = 1,
7147 struct hid_expect expect_acquire[] =
7150 .code = IOCTL_HID_WRITE_REPORT,
7151 .report_id = 1,
7152 .report_len = 2,
7153 .report_buf = {1, 0x01},
7156 .code = IOCTL_HID_WRITE_REPORT,
7157 .report_id = 8,
7158 .report_len = 2,
7159 .report_buf = {8, 0x19},
7162 struct hid_expect expect_reset[] =
7165 .code = IOCTL_HID_WRITE_REPORT,
7166 .report_id = 1,
7167 .report_len = 2,
7168 .report_buf = {1, 0x01},
7171 struct hid_expect expect_set_device_gain_1 =
7173 .code = IOCTL_HID_WRITE_REPORT,
7174 .report_id = 8,
7175 .report_len = 2,
7176 .report_buf = {8, 0x19},
7178 struct hid_expect expect_set_device_gain_2 =
7180 .code = IOCTL_HID_WRITE_REPORT,
7181 .report_id = 8,
7182 .report_len = 2,
7183 .report_buf = {8, 0x33},
7186 const DIDEVICEINSTANCEW expect_devinst =
7188 .dwSize = sizeof(DIDEVICEINSTANCEW),
7189 .guidInstance = expect_guid_product,
7190 .guidProduct = expect_guid_product,
7191 .dwDevType = version >= 0x800 ? DIDEVTYPE_HID | (DI8DEVTYPEJOYSTICK_LIMITED << 8) | DI8DEVTYPE_JOYSTICK
7192 : DIDEVTYPE_HID | (DIDEVTYPEJOYSTICK_UNKNOWN << 8) | DIDEVTYPE_JOYSTICK,
7193 .tszInstanceName = L"Wine test root driver",
7194 .tszProductName = L"Wine test root driver",
7195 .guidFFDriver = IID_IDirectInputPIDDriver,
7196 .wUsagePage = HID_USAGE_PAGE_GENERIC,
7197 .wUsage = HID_USAGE_GENERIC_JOYSTICK,
7199 const DIDEVICEOBJECTINSTANCEW expect_objects_5[] =
7202 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7203 .guidType = GUID_XAxis,
7204 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(0)|DIDFT_FFACTUATOR,
7205 .dwFlags = DIDOI_ASPECTPOSITION|DIDOI_FFACTUATOR,
7206 .tszName = L"X Axis",
7207 .wCollectionNumber = 1,
7208 .wUsagePage = HID_USAGE_PAGE_GENERIC,
7209 .wUsage = HID_USAGE_GENERIC_X,
7210 .wReportId = 1,
7213 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7214 .guidType = GUID_YAxis,
7215 .dwOfs = 0x4,
7216 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(1)|DIDFT_FFACTUATOR,
7217 .dwFlags = DIDOI_ASPECTPOSITION|DIDOI_FFACTUATOR,
7218 .tszName = L"Y Axis",
7219 .wCollectionNumber = 1,
7220 .wUsagePage = HID_USAGE_PAGE_GENERIC,
7221 .wUsage = HID_USAGE_GENERIC_Y,
7222 .wReportId = 1,
7225 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7226 .guidType = GUID_ZAxis,
7227 .dwOfs = 0x8,
7228 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(2)|DIDFT_FFACTUATOR,
7229 .dwFlags = DIDOI_ASPECTPOSITION|DIDOI_FFACTUATOR,
7230 .tszName = L"Z Axis",
7231 .wCollectionNumber = 1,
7232 .wUsagePage = HID_USAGE_PAGE_GENERIC,
7233 .wUsage = HID_USAGE_GENERIC_Z,
7234 .wReportId = 1,
7237 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7238 .guidType = GUID_Button,
7239 .dwOfs = 0x30,
7240 .dwType = DIDFT_PSHBUTTON|DIDFT_MAKEINSTANCE(0)|DIDFT_FFEFFECTTRIGGER,
7241 .dwFlags = DIDOI_FFEFFECTTRIGGER,
7242 .tszName = L"Button 0",
7243 .wCollectionNumber = 1,
7244 .wUsagePage = HID_USAGE_PAGE_BUTTON,
7245 .wUsage = 0x1,
7246 .wReportId = 1,
7249 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7250 .guidType = GUID_Button,
7251 .dwOfs = 0x31,
7252 .dwType = DIDFT_PSHBUTTON|DIDFT_MAKEINSTANCE(1)|DIDFT_FFEFFECTTRIGGER,
7253 .dwFlags = DIDOI_FFEFFECTTRIGGER,
7254 .tszName = L"Button 1",
7255 .wCollectionNumber = 1,
7256 .wUsagePage = HID_USAGE_PAGE_BUTTON,
7257 .wUsage = 0x2,
7258 .wReportId = 1,
7261 const DIDEVICEOBJECTINSTANCEW expect_objects[] =
7264 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7265 .guidType = GUID_ZAxis,
7266 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(2)|DIDFT_FFACTUATOR,
7267 .dwFlags = DIDOI_ASPECTPOSITION|DIDOI_FFACTUATOR,
7268 .tszName = L"Z Axis",
7269 .wCollectionNumber = 1,
7270 .wUsagePage = HID_USAGE_PAGE_GENERIC,
7271 .wUsage = HID_USAGE_GENERIC_Z,
7272 .wReportId = 1,
7275 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7276 .guidType = GUID_YAxis,
7277 .dwOfs = 0x4,
7278 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(1)|DIDFT_FFACTUATOR,
7279 .dwFlags = DIDOI_ASPECTPOSITION|DIDOI_FFACTUATOR,
7280 .tszName = L"Y Axis",
7281 .wCollectionNumber = 1,
7282 .wUsagePage = HID_USAGE_PAGE_GENERIC,
7283 .wUsage = HID_USAGE_GENERIC_Y,
7284 .wReportId = 1,
7287 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7288 .guidType = GUID_XAxis,
7289 .dwOfs = 0x8,
7290 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(0)|DIDFT_FFACTUATOR,
7291 .dwFlags = DIDOI_ASPECTPOSITION|DIDOI_FFACTUATOR,
7292 .tszName = L"X Axis",
7293 .wCollectionNumber = 1,
7294 .wUsagePage = HID_USAGE_PAGE_GENERIC,
7295 .wUsage = HID_USAGE_GENERIC_X,
7296 .wReportId = 1,
7299 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7300 .guidType = GUID_Button,
7301 .dwOfs = version >= 0x800 ? 0x68 : 0x10,
7302 .dwType = DIDFT_PSHBUTTON|DIDFT_MAKEINSTANCE(0)|DIDFT_FFEFFECTTRIGGER,
7303 .dwFlags = DIDOI_FFEFFECTTRIGGER,
7304 .tszName = L"Button 0",
7305 .wCollectionNumber = 1,
7306 .wUsagePage = HID_USAGE_PAGE_BUTTON,
7307 .wUsage = 0x1,
7308 .wReportId = 1,
7311 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7312 .guidType = GUID_Button,
7313 .dwOfs = version >= 0x800 ? 0x69 : 0x11,
7314 .dwType = DIDFT_PSHBUTTON|DIDFT_MAKEINSTANCE(1)|DIDFT_FFEFFECTTRIGGER,
7315 .dwFlags = DIDOI_FFEFFECTTRIGGER,
7316 .tszName = L"Button 1",
7317 .wCollectionNumber = 1,
7318 .wUsagePage = HID_USAGE_PAGE_BUTTON,
7319 .wUsage = 0x2,
7320 .wReportId = 1,
7323 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7324 .guidType = GUID_Unknown,
7325 .dwOfs = version >= 0x800 ? 0x70 : 0,
7326 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(12)|DIDFT_OUTPUT,
7327 .dwFlags = 0x80008000,
7328 .tszName = L"DC Device Reset",
7329 .wCollectionNumber = 4,
7330 .wUsagePage = HID_USAGE_PAGE_PID,
7331 .wUsage = PID_USAGE_DC_DEVICE_RESET,
7332 .wReportId = 1,
7335 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7336 .guidType = GUID_Unknown,
7337 .dwOfs = version >= 0x800 ? 0x10 : 0,
7338 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(13)|DIDFT_OUTPUT,
7339 .dwFlags = 0x80008000,
7340 .tszName = L"Effect Block Index",
7341 .wCollectionNumber = 5,
7342 .wUsagePage = HID_USAGE_PAGE_PID,
7343 .wUsage = PID_USAGE_EFFECT_BLOCK_INDEX,
7344 .wReportId = 2,
7347 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7348 .guidType = GUID_Unknown,
7349 .dwOfs = version >= 0x800 ? 0x71 : 0,
7350 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(14)|DIDFT_OUTPUT,
7351 .dwFlags = 0x80008000,
7352 .tszName = L"Op Effect Start",
7353 .wCollectionNumber = 6,
7354 .wUsagePage = HID_USAGE_PAGE_PID,
7355 .wUsage = PID_USAGE_OP_EFFECT_START,
7356 .wReportId = 2,
7359 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7360 .guidType = GUID_Unknown,
7361 .dwOfs = version >= 0x800 ? 0x72 : 0,
7362 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(15)|DIDFT_OUTPUT,
7363 .dwFlags = 0x80008000,
7364 .tszName = L"Op Effect Start Solo",
7365 .wCollectionNumber = 6,
7366 .wUsagePage = HID_USAGE_PAGE_PID,
7367 .wUsage = PID_USAGE_OP_EFFECT_START_SOLO,
7368 .wReportId = 2,
7371 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7372 .guidType = GUID_Unknown,
7373 .dwOfs = version >= 0x800 ? 0x73 : 0,
7374 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(16)|DIDFT_OUTPUT,
7375 .dwFlags = 0x80008000,
7376 .tszName = L"Op Effect Stop",
7377 .wCollectionNumber = 6,
7378 .wUsagePage = HID_USAGE_PAGE_PID,
7379 .wUsage = PID_USAGE_OP_EFFECT_STOP,
7380 .wReportId = 2,
7383 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7384 .guidType = GUID_Unknown,
7385 .dwOfs = version >= 0x800 ? 0x14 : 0,
7386 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(17)|DIDFT_OUTPUT,
7387 .dwFlags = 0x80008000,
7388 .tszName = L"Loop Count",
7389 .wCollectionNumber = 5,
7390 .wUsagePage = HID_USAGE_PAGE_PID,
7391 .wUsage = PID_USAGE_LOOP_COUNT,
7392 .wReportId = 2,
7395 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7396 .guidType = GUID_Unknown,
7397 .dwOfs = version >= 0x800 ? 0x18 : 0,
7398 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(18)|DIDFT_OUTPUT,
7399 .dwFlags = 0x80008000,
7400 .tszName = L"Effect Block Index",
7401 .wCollectionNumber = 7,
7402 .wUsagePage = HID_USAGE_PAGE_PID,
7403 .wUsage = PID_USAGE_EFFECT_BLOCK_INDEX,
7404 .wReportId = 3,
7407 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7408 .guidType = GUID_Unknown,
7409 .dwOfs = version >= 0x800 ? 0x74 : 0,
7410 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(19)|DIDFT_OUTPUT,
7411 .dwFlags = 0x80008000,
7412 .tszName = L"ET Square",
7413 .wCollectionNumber = 8,
7414 .wUsagePage = HID_USAGE_PAGE_PID,
7415 .wUsage = PID_USAGE_ET_SQUARE,
7416 .wReportId = 3,
7419 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7420 .guidType = GUID_Unknown,
7421 .dwOfs = version >= 0x800 ? 0x75 : 0,
7422 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(20)|DIDFT_OUTPUT,
7423 .dwFlags = 0x80008000,
7424 .tszName = L"ET Sine",
7425 .wCollectionNumber = 8,
7426 .wUsagePage = HID_USAGE_PAGE_PID,
7427 .wUsage = PID_USAGE_ET_SINE,
7428 .wReportId = 3,
7431 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7432 .guidType = GUID_Unknown,
7433 .dwOfs = version >= 0x800 ? 0x76 : 0,
7434 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(21)|DIDFT_OUTPUT,
7435 .dwFlags = 0x80008000,
7436 .tszName = L"ET Spring",
7437 .wCollectionNumber = 8,
7438 .wUsagePage = HID_USAGE_PAGE_PID,
7439 .wUsage = PID_USAGE_ET_SPRING,
7440 .wReportId = 3,
7443 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7444 .guidType = GUID_Unknown,
7445 .dwOfs = version >= 0x800 ? 0x77 : 0,
7446 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(22)|DIDFT_OUTPUT,
7447 .dwFlags = 0x80008000,
7448 .tszName = L"Z Axis",
7449 .wCollectionNumber = 9,
7450 .wUsagePage = HID_USAGE_PAGE_GENERIC,
7451 .wUsage = HID_USAGE_GENERIC_Z,
7452 .wReportId = 3,
7455 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7456 .guidType = GUID_Unknown,
7457 .dwOfs = version >= 0x800 ? 0x78 : 0,
7458 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(23)|DIDFT_OUTPUT,
7459 .dwFlags = 0x80008000,
7460 .tszName = L"Y Axis",
7461 .wCollectionNumber = 9,
7462 .wUsagePage = HID_USAGE_PAGE_GENERIC,
7463 .wUsage = HID_USAGE_GENERIC_Y,
7464 .wReportId = 3,
7467 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7468 .guidType = GUID_Unknown,
7469 .dwOfs = version >= 0x800 ? 0x79 : 0,
7470 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(24)|DIDFT_OUTPUT,
7471 .dwFlags = 0x80008000,
7472 .tszName = L"X Axis",
7473 .wCollectionNumber = 9,
7474 .wUsagePage = HID_USAGE_PAGE_GENERIC,
7475 .wUsage = HID_USAGE_GENERIC_X,
7476 .wReportId = 3,
7479 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7480 .guidType = GUID_Unknown,
7481 .dwOfs = version >= 0x800 ? 0x7a : 0,
7482 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(25)|DIDFT_OUTPUT,
7483 .dwFlags = 0x80008000,
7484 .tszName = L"Direction Enable",
7485 .wCollectionNumber = 7,
7486 .wUsagePage = HID_USAGE_PAGE_PID,
7487 .wUsage = PID_USAGE_DIRECTION_ENABLE,
7488 .wReportId = 3,
7491 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7492 .guidType = GUID_Unknown,
7493 .dwOfs = version >= 0x800 ? 0x1c : 0,
7494 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(26)|DIDFT_OUTPUT,
7495 .dwFlags = 0x80008000,
7496 .tszName = L"Start Delay",
7497 .wCollectionNumber = 7,
7498 .wUsagePage = HID_USAGE_PAGE_PID,
7499 .wUsage = PID_USAGE_START_DELAY,
7500 .wReportId = 3,
7501 .dwDimension = 0x1003,
7502 .wExponent = -3,
7505 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7506 .guidType = GUID_Unknown,
7507 .dwOfs = version >= 0x800 ? 0x20 : 0,
7508 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(27)|DIDFT_OUTPUT,
7509 .dwFlags = 0x80008000,
7510 .tszName = L"Duration",
7511 .wCollectionNumber = 7,
7512 .wUsagePage = HID_USAGE_PAGE_PID,
7513 .wUsage = PID_USAGE_DURATION,
7514 .wReportId = 3,
7515 .dwDimension = 0x1003,
7516 .wExponent = -3,
7519 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7520 .guidType = GUID_Unknown,
7521 .dwOfs = version >= 0x800 ? 0x24 : 0,
7522 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(28)|DIDFT_OUTPUT,
7523 .dwFlags = 0x80008000,
7524 .tszName = L"Trigger Button",
7525 .wCollectionNumber = 7,
7526 .wUsagePage = HID_USAGE_PAGE_PID,
7527 .wUsage = PID_USAGE_TRIGGER_BUTTON,
7528 .wReportId = 3,
7531 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7532 .guidType = GUID_Unknown,
7533 .dwOfs = version >= 0x800 ? 0x28 : 0,
7534 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(29)|DIDFT_OUTPUT,
7535 .dwFlags = 0x80008000,
7536 .tszName = L"Unknown 29",
7537 .wCollectionNumber = 10,
7538 .wUsagePage = HID_USAGE_PAGE_ORDINAL,
7539 .wUsage = 2,
7540 .wReportId = 3,
7541 .wExponent = -2,
7544 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7545 .guidType = GUID_Unknown,
7546 .dwOfs = version >= 0x800 ? 0x2c : 0,
7547 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(30)|DIDFT_OUTPUT,
7548 .dwFlags = 0x80008000,
7549 .tszName = L"Unknown 30",
7550 .wCollectionNumber = 10,
7551 .wUsagePage = HID_USAGE_PAGE_ORDINAL,
7552 .wUsage = 1,
7553 .wReportId = 3,
7554 .wExponent = -2,
7557 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7558 .guidType = GUID_Unknown,
7559 .dwOfs = version >= 0x800 ? 0x30 : 0,
7560 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(31)|DIDFT_OUTPUT,
7561 .dwFlags = 0x80008000,
7562 .tszName = L"Magnitude",
7563 .wCollectionNumber = 11,
7564 .wUsagePage = HID_USAGE_PAGE_PID,
7565 .wUsage = PID_USAGE_MAGNITUDE,
7566 .wReportId = 5,
7569 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7570 .guidType = GUID_Unknown,
7571 .dwOfs = version >= 0x800 ? 0x34 : 0,
7572 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(32)|DIDFT_OUTPUT,
7573 .dwFlags = 0x80008000,
7574 .tszName = L"Fade Level",
7575 .wCollectionNumber = 12,
7576 .wUsagePage = HID_USAGE_PAGE_PID,
7577 .wUsage = PID_USAGE_FADE_LEVEL,
7578 .wReportId = 6,
7581 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7582 .guidType = GUID_Unknown,
7583 .dwOfs = version >= 0x800 ? 0x38 : 0,
7584 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(33)|DIDFT_OUTPUT,
7585 .dwFlags = 0x80008000,
7586 .tszName = L"Attack Level",
7587 .wCollectionNumber = 12,
7588 .wUsagePage = HID_USAGE_PAGE_PID,
7589 .wUsage = PID_USAGE_ATTACK_LEVEL,
7590 .wReportId = 6,
7593 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7594 .guidType = GUID_Unknown,
7595 .dwOfs = version >= 0x800 ? 0x3c : 0,
7596 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(34)|DIDFT_OUTPUT,
7597 .dwFlags = 0x80008000,
7598 .tszName = L"Fade Time",
7599 .wCollectionNumber = 12,
7600 .wUsagePage = HID_USAGE_PAGE_PID,
7601 .wUsage = PID_USAGE_FADE_TIME,
7602 .wReportId = 6,
7603 .dwDimension = 0x1003,
7604 .wExponent = -3,
7607 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7608 .guidType = GUID_Unknown,
7609 .dwOfs = version >= 0x800 ? 0x40 : 0,
7610 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(35)|DIDFT_OUTPUT,
7611 .dwFlags = 0x80008000,
7612 .tszName = L"Attack Time",
7613 .wCollectionNumber = 12,
7614 .wUsagePage = HID_USAGE_PAGE_PID,
7615 .wUsage = PID_USAGE_ATTACK_TIME,
7616 .wReportId = 6,
7617 .dwDimension = 0x1003,
7618 .wExponent = -3,
7621 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7622 .guidType = GUID_Unknown,
7623 .dwOfs = version >= 0x800 ? 0x44 : 0,
7624 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(36)|DIDFT_OUTPUT,
7625 .dwFlags = 0x80008000,
7626 .tszName = L"Unknown 36",
7627 .wCollectionNumber = 14,
7628 .wUsagePage = HID_USAGE_PAGE_ORDINAL,
7629 .wUsage = 2,
7630 .wReportId = 7,
7633 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7634 .guidType = GUID_Unknown,
7635 .dwOfs = version >= 0x800 ? 0x48 : 0,
7636 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(37)|DIDFT_OUTPUT,
7637 .dwFlags = 0x80008000,
7638 .tszName = L"Unknown 37",
7639 .wCollectionNumber = 14,
7640 .wUsagePage = HID_USAGE_PAGE_ORDINAL,
7641 .wUsage = 1,
7642 .wReportId = 7,
7645 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7646 .guidType = GUID_Unknown,
7647 .dwOfs = version >= 0x800 ? 0x4c : 0,
7648 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(38)|DIDFT_OUTPUT,
7649 .dwFlags = 0x80008000,
7650 .tszName = L"CP Offset",
7651 .wCollectionNumber = 13,
7652 .wUsagePage = HID_USAGE_PAGE_PID,
7653 .wUsage = PID_USAGE_CP_OFFSET,
7654 .wReportId = 7,
7657 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7658 .guidType = GUID_Unknown,
7659 .dwOfs = version >= 0x800 ? 0x50 : 0,
7660 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(39)|DIDFT_OUTPUT,
7661 .dwFlags = 0x80008000,
7662 .tszName = L"Negative Coefficient",
7663 .wCollectionNumber = 13,
7664 .wUsagePage = HID_USAGE_PAGE_PID,
7665 .wUsage = PID_USAGE_NEGATIVE_COEFFICIENT,
7666 .wReportId = 7,
7669 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7670 .guidType = GUID_Unknown,
7671 .dwOfs = version >= 0x800 ? 0x54 : 0,
7672 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(40)|DIDFT_OUTPUT,
7673 .dwFlags = 0x80008000,
7674 .tszName = L"Positive Coefficient",
7675 .wCollectionNumber = 13,
7676 .wUsagePage = HID_USAGE_PAGE_PID,
7677 .wUsage = PID_USAGE_POSITIVE_COEFFICIENT,
7678 .wReportId = 7,
7681 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7682 .guidType = GUID_Unknown,
7683 .dwOfs = version >= 0x800 ? 0x58 : 0,
7684 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(41)|DIDFT_OUTPUT,
7685 .dwFlags = 0x80008000,
7686 .tszName = L"Negative Saturation",
7687 .wCollectionNumber = 13,
7688 .wUsagePage = HID_USAGE_PAGE_PID,
7689 .wUsage = PID_USAGE_NEGATIVE_SATURATION,
7690 .wReportId = 7,
7693 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7694 .guidType = GUID_Unknown,
7695 .dwOfs = version >= 0x800 ? 0x5c : 0,
7696 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(42)|DIDFT_OUTPUT,
7697 .dwFlags = 0x80008000,
7698 .tszName = L"Positive Saturation",
7699 .wCollectionNumber = 13,
7700 .wUsagePage = HID_USAGE_PAGE_PID,
7701 .wUsage = PID_USAGE_POSITIVE_SATURATION,
7702 .wReportId = 7,
7705 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7706 .guidType = GUID_Unknown,
7707 .dwOfs = version >= 0x800 ? 0x60 : 0,
7708 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(43)|DIDFT_OUTPUT,
7709 .dwFlags = 0x80008000,
7710 .tszName = L"Dead Band",
7711 .wCollectionNumber = 13,
7712 .wUsagePage = HID_USAGE_PAGE_PID,
7713 .wUsage = PID_USAGE_DEAD_BAND,
7714 .wReportId = 7,
7717 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7718 .guidType = GUID_Unknown,
7719 .dwOfs = version >= 0x800 ? 0x64 : 0,
7720 .dwType = DIDFT_NODATA|DIDFT_MAKEINSTANCE(44)|DIDFT_OUTPUT,
7721 .dwFlags = 0x80008000,
7722 .tszName = L"Device Gain",
7723 .wCollectionNumber = 15,
7724 .wUsagePage = HID_USAGE_PAGE_PID,
7725 .wUsage = PID_USAGE_DEVICE_GAIN,
7726 .wReportId = 8,
7729 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7730 .guidType = GUID_Unknown,
7731 .dwType = DIDFT_COLLECTION|DIDFT_NODATA|DIDFT_MAKEINSTANCE(0),
7732 .tszName = L"Collection 0 - Joystick",
7733 .wUsagePage = HID_USAGE_PAGE_GENERIC,
7734 .wUsage = HID_USAGE_GENERIC_JOYSTICK,
7737 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7738 .guidType = GUID_Unknown,
7739 .dwType = DIDFT_COLLECTION|DIDFT_NODATA|DIDFT_MAKEINSTANCE(1),
7740 .tszName = L"Collection 1 - Joystick",
7741 .wUsagePage = HID_USAGE_PAGE_GENERIC,
7742 .wUsage = HID_USAGE_GENERIC_JOYSTICK,
7745 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7746 .guidType = GUID_Unknown,
7747 .dwType = DIDFT_COLLECTION|DIDFT_NODATA|DIDFT_MAKEINSTANCE(2),
7748 .tszName = L"Collection 2 - PID State Report",
7749 .wUsagePage = HID_USAGE_PAGE_PID,
7750 .wUsage = PID_USAGE_STATE_REPORT,
7753 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7754 .guidType = GUID_Unknown,
7755 .dwType = DIDFT_COLLECTION|DIDFT_NODATA|DIDFT_MAKEINSTANCE(3),
7756 .tszName = L"Collection 3 - PID Device Control Report",
7757 .wUsagePage = HID_USAGE_PAGE_PID,
7758 .wUsage = PID_USAGE_DEVICE_CONTROL_REPORT,
7761 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7762 .guidType = GUID_Unknown,
7763 .dwType = DIDFT_COLLECTION|DIDFT_NODATA|DIDFT_MAKEINSTANCE(4),
7764 .tszName = L"Collection 4 - PID Device Control",
7765 .wCollectionNumber = 3,
7766 .wUsagePage = HID_USAGE_PAGE_PID,
7767 .wUsage = PID_USAGE_DEVICE_CONTROL,
7770 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7771 .guidType = GUID_Unknown,
7772 .dwType = DIDFT_COLLECTION|DIDFT_NODATA|DIDFT_MAKEINSTANCE(5),
7773 .tszName = L"Collection 5 - Effect Operation Report",
7774 .wUsagePage = HID_USAGE_PAGE_PID,
7775 .wUsage = PID_USAGE_EFFECT_OPERATION_REPORT,
7778 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7779 .guidType = GUID_Unknown,
7780 .dwType = DIDFT_COLLECTION|DIDFT_NODATA|DIDFT_MAKEINSTANCE(6),
7781 .tszName = L"Collection 6 - Effect Operation",
7782 .wCollectionNumber = 5,
7783 .wUsagePage = HID_USAGE_PAGE_PID,
7784 .wUsage = PID_USAGE_EFFECT_OPERATION,
7787 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7788 .guidType = GUID_Unknown,
7789 .dwType = DIDFT_COLLECTION|DIDFT_NODATA|DIDFT_MAKEINSTANCE(7),
7790 .tszName = L"Collection 7 - Set Effect Report",
7791 .wUsagePage = HID_USAGE_PAGE_PID,
7792 .wUsage = PID_USAGE_SET_EFFECT_REPORT,
7795 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7796 .guidType = GUID_Unknown,
7797 .dwType = DIDFT_COLLECTION|DIDFT_NODATA|DIDFT_MAKEINSTANCE(8),
7798 .tszName = L"Collection 8 - Effect Type",
7799 .wCollectionNumber = 7,
7800 .wUsagePage = HID_USAGE_PAGE_PID,
7801 .wUsage = PID_USAGE_EFFECT_TYPE,
7804 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7805 .guidType = GUID_Unknown,
7806 .dwType = DIDFT_COLLECTION|DIDFT_NODATA|DIDFT_MAKEINSTANCE(9),
7807 .tszName = L"Collection 9 - Axes Enable",
7808 .wCollectionNumber = 7,
7809 .wUsagePage = HID_USAGE_PAGE_PID,
7810 .wUsage = PID_USAGE_AXES_ENABLE,
7813 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7814 .guidType = GUID_Unknown,
7815 .dwType = DIDFT_COLLECTION|DIDFT_NODATA|DIDFT_MAKEINSTANCE(10),
7816 .tszName = L"Collection 10 - Direction",
7817 .wCollectionNumber = 7,
7818 .wUsagePage = HID_USAGE_PAGE_PID,
7819 .wUsage = PID_USAGE_DIRECTION,
7822 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7823 .guidType = GUID_Unknown,
7824 .dwType = DIDFT_COLLECTION|DIDFT_NODATA|DIDFT_MAKEINSTANCE(11),
7825 .tszName = L"Collection 11 - Set Periodic Report",
7826 .wUsagePage = HID_USAGE_PAGE_PID,
7827 .wUsage = PID_USAGE_SET_PERIODIC_REPORT,
7830 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7831 .guidType = GUID_Unknown,
7832 .dwType = DIDFT_COLLECTION|DIDFT_NODATA|DIDFT_MAKEINSTANCE(12),
7833 .tszName = L"Collection 12 - Set Envelope Report",
7834 .wUsagePage = HID_USAGE_PAGE_PID,
7835 .wUsage = PID_USAGE_SET_ENVELOPE_REPORT,
7838 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7839 .guidType = GUID_Unknown,
7840 .dwType = DIDFT_COLLECTION|DIDFT_NODATA|DIDFT_MAKEINSTANCE(13),
7841 .tszName = L"Collection 13 - Set Condition Report",
7842 .wUsagePage = HID_USAGE_PAGE_PID,
7843 .wUsage = PID_USAGE_SET_CONDITION_REPORT,
7846 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7847 .guidType = GUID_Unknown,
7848 .dwType = DIDFT_COLLECTION|DIDFT_NODATA|DIDFT_MAKEINSTANCE(14),
7849 .tszName = L"Collection 14 - Type Specific Block Offset",
7850 .wCollectionNumber = 13,
7851 .wUsagePage = HID_USAGE_PAGE_PID,
7852 .wUsage = PID_USAGE_TYPE_SPECIFIC_BLOCK_OFFSET,
7855 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
7856 .guidType = GUID_Unknown,
7857 .dwType = DIDFT_COLLECTION|DIDFT_NODATA|DIDFT_MAKEINSTANCE(15),
7858 .tszName = L"Collection 15 - Device Gain Report",
7859 .wUsagePage = HID_USAGE_PAGE_PID,
7860 .wUsage = PID_USAGE_DEVICE_GAIN_REPORT,
7863 const DIEFFECTINFOW expect_effects[] =
7866 .dwSize = sizeof(DIEFFECTINFOW),
7867 .guid = GUID_Square,
7868 .dwEffType = DIEFT_PERIODIC | DIEFT_STARTDELAY | DIEFT_FFFADE | DIEFT_FFATTACK,
7869 .dwStaticParams = DIEP_AXES | DIEP_DIRECTION | DIEP_TYPESPECIFICPARAMS | DIEP_STARTDELAY |
7870 DIEP_DURATION | DIEP_TRIGGERBUTTON | DIEP_ENVELOPE,
7871 .dwDynamicParams = DIEP_AXES | DIEP_DIRECTION | DIEP_TYPESPECIFICPARAMS | DIEP_STARTDELAY |
7872 DIEP_DURATION | DIEP_TRIGGERBUTTON | DIEP_ENVELOPE,
7873 .tszName = L"GUID_Square",
7876 .dwSize = sizeof(DIEFFECTINFOW),
7877 .guid = GUID_Sine,
7878 .dwEffType = DIEFT_PERIODIC | DIEFT_STARTDELAY | DIEFT_FFFADE | DIEFT_FFATTACK,
7879 .dwStaticParams = DIEP_AXES | DIEP_DIRECTION | DIEP_TYPESPECIFICPARAMS | DIEP_STARTDELAY |
7880 DIEP_DURATION | DIEP_TRIGGERBUTTON | DIEP_ENVELOPE,
7881 .dwDynamicParams = DIEP_AXES | DIEP_DIRECTION | DIEP_TYPESPECIFICPARAMS | DIEP_STARTDELAY |
7882 DIEP_DURATION | DIEP_TRIGGERBUTTON | DIEP_ENVELOPE,
7883 .tszName = L"GUID_Sine",
7886 .dwSize = sizeof(DIEFFECTINFOW),
7887 .guid = GUID_Spring,
7888 .dwEffType = DIEFT_CONDITION | DIEFT_STARTDELAY | DIEFT_DEADBAND | DIEFT_SATURATION,
7889 .dwStaticParams = DIEP_AXES | DIEP_DIRECTION | DIEP_TYPESPECIFICPARAMS | DIEP_STARTDELAY |
7890 DIEP_DURATION,
7891 .dwDynamicParams = DIEP_AXES | DIEP_DIRECTION | DIEP_TYPESPECIFICPARAMS | DIEP_STARTDELAY |
7892 DIEP_DURATION,
7893 .tszName = L"GUID_Spring",
7897 struct check_objects_todos todo_objects_5[ARRAY_SIZE(expect_objects_5)] =
7899 {.guid = TRUE, .type = TRUE, .usage = TRUE, .name = TRUE},
7900 {0},
7901 {.guid = TRUE, .type = TRUE, .usage = TRUE, .name = TRUE},
7903 struct check_objects_params check_objects_params =
7905 .version = version,
7906 .expect_count = version < 0x700 ? ARRAY_SIZE(expect_objects_5) : ARRAY_SIZE(expect_objects),
7907 .expect_objs = version < 0x700 ? expect_objects_5 : expect_objects,
7908 .todo_objs = version < 0x700 ? todo_objects_5 : NULL,
7909 .todo_extra = version < 0x700 ? TRUE : FALSE,
7911 struct check_effects_params check_effects_params =
7913 .expect_count = ARRAY_SIZE(expect_effects),
7914 .expect_effects = expect_effects,
7916 DIPROPDWORD prop_dword =
7918 .diph =
7920 .dwSize = sizeof(DIPROPDWORD),
7921 .dwHeaderSize = sizeof(DIPROPHEADER),
7922 .dwHow = DIPH_DEVICE,
7925 DIPROPGUIDANDPATH prop_guid_path =
7927 .diph =
7929 .dwSize = sizeof(DIPROPGUIDANDPATH),
7930 .dwHeaderSize = sizeof(DIPROPHEADER),
7931 .dwHow = DIPH_DEVICE,
7934 DIDEVICEINSTANCEW devinst = {.dwSize = sizeof(DIDEVICEINSTANCEW)};
7935 WCHAR cwd[MAX_PATH], tempdir[MAX_PATH];
7936 DIDEVICEOBJECTDATA objdata = {0};
7937 DIEFFECTINFOW effectinfo = {0};
7938 IDirectInputDevice8W *device;
7939 DIEFFESCAPE escape = {0};
7940 DIDEVCAPS caps = {0};
7941 char buffer[1024];
7942 ULONG res, ref;
7943 HANDLE file;
7944 HRESULT hr;
7945 HWND hwnd;
7947 winetest_push_context( "version %#x", version );
7949 GetCurrentDirectoryW( ARRAY_SIZE(cwd), cwd );
7950 GetTempPathW( ARRAY_SIZE(tempdir), tempdir );
7951 SetCurrentDirectoryW( tempdir );
7953 cleanup_registry_keys();
7954 if (!dinput_driver_start( report_descriptor, sizeof(report_descriptor), &hid_caps, NULL, 0 )) goto done;
7955 if (FAILED(hr = create_dinput_device( version, &devinst, &device ))) goto done;
7957 hr = IDirectInputDevice8_GetDeviceInfo( device, &devinst );
7958 ok( hr == DI_OK, "GetDeviceInfo returned %#x\n", hr );
7959 check_member( devinst, expect_devinst, "%d", dwSize );
7960 todo_wine
7961 check_member_guid( devinst, expect_devinst, guidInstance );
7962 check_member_guid( devinst, expect_devinst, guidProduct );
7963 check_member( devinst, expect_devinst, "%#x", dwDevType );
7964 todo_wine
7965 check_member_wstr( devinst, expect_devinst, tszInstanceName );
7966 todo_wine
7967 check_member_wstr( devinst, expect_devinst, tszProductName );
7968 check_member_guid( devinst, expect_devinst, guidFFDriver );
7969 check_member( devinst, expect_devinst, "%04x", wUsagePage );
7970 check_member( devinst, expect_devinst, "%04x", wUsage );
7972 caps.dwSize = sizeof(DIDEVCAPS);
7973 hr = IDirectInputDevice8_GetCapabilities( device, &caps );
7974 ok( hr == DI_OK, "GetCapabilities returned %#x\n", hr );
7975 check_member( caps, expect_caps, "%d", dwSize );
7976 check_member( caps, expect_caps, "%#x", dwFlags );
7977 check_member( caps, expect_caps, "%#x", dwDevType );
7978 check_member( caps, expect_caps, "%d", dwAxes );
7979 check_member( caps, expect_caps, "%d", dwButtons );
7980 check_member( caps, expect_caps, "%d", dwPOVs );
7981 check_member( caps, expect_caps, "%d", dwFFSamplePeriod );
7982 check_member( caps, expect_caps, "%d", dwFFMinTimeResolution );
7983 check_member( caps, expect_caps, "%d", dwFirmwareRevision );
7984 check_member( caps, expect_caps, "%d", dwHardwareRevision );
7985 check_member( caps, expect_caps, "%d", dwFFDriverVersion );
7987 prop_dword.dwData = 0xdeadbeef;
7988 hr = IDirectInputDevice8_GetProperty( device, DIPROP_FFGAIN, &prop_dword.diph );
7989 ok( hr == DI_OK, "GetProperty DIPROP_FFGAIN returned %#x\n", hr );
7990 ok( prop_dword.dwData == 10000, "got %u expected %u\n", prop_dword.dwData, 10000 );
7992 hr = IDirectInputDevice8_GetProperty( device, DIPROP_FFLOAD, &prop_dword.diph );
7993 ok( hr == DIERR_NOTEXCLUSIVEACQUIRED, "GetProperty DIPROP_FFLOAD returned %#x\n", hr );
7995 hr = IDirectInputDevice8_EnumObjects( device, check_objects, &check_objects_params, DIDFT_ALL );
7996 ok( hr == DI_OK, "EnumObjects returned %#x\n", hr );
7997 ok( check_objects_params.index >= check_objects_params.expect_count, "missing %u objects\n",
7998 check_objects_params.expect_count - check_objects_params.index );
8000 res = 0;
8001 hr = IDirectInputDevice8_EnumEffects( device, check_effect_count, &res, 0xfe );
8002 ok( hr == DI_OK, "EnumEffects returned %#x\n", hr );
8003 ok( res == 0, "got %u expected %u\n", res, 0 );
8004 res = 0;
8005 hr = IDirectInputDevice8_EnumEffects( device, check_effect_count, &res, DIEFT_PERIODIC );
8006 ok( hr == DI_OK, "EnumEffects returned %#x\n", hr );
8007 ok( res == 2, "got %u expected %u\n", res, 2 );
8008 hr = IDirectInputDevice8_EnumEffects( device, check_effects, &check_effects_params, DIEFT_ALL );
8009 ok( hr == DI_OK, "EnumEffects returned %#x\n", hr );
8010 ok( check_effects_params.index >= check_effects_params.expect_count, "missing %u effects\n",
8011 check_effects_params.expect_count - check_effects_params.index );
8013 effectinfo.dwSize = sizeof(DIEFFECTINFOW);
8014 hr = IDirectInputDevice8_GetEffectInfo( device, &effectinfo, &GUID_Sine );
8015 ok( hr == DI_OK, "GetEffectInfo returned %#x\n", hr );
8016 check_member_guid( effectinfo, expect_effects[1], guid );
8017 check_member( effectinfo, expect_effects[1], "%#x", dwEffType );
8018 check_member( effectinfo, expect_effects[1], "%#x", dwStaticParams );
8019 check_member( effectinfo, expect_effects[1], "%#x", dwDynamicParams );
8020 check_member_wstr( effectinfo, expect_effects[1], tszName );
8022 hr = IDirectInputDevice8_SetDataFormat( device, &c_dfDIJoystick2 );
8023 ok( hr == DI_OK, "SetDataFormat returned: %#x\n", hr );
8025 hr = IDirectInputDevice8_GetProperty( device, DIPROP_GUIDANDPATH, &prop_guid_path.diph );
8026 ok( hr == DI_OK, "GetProperty DIPROP_GUIDANDPATH returned %#x\n", hr );
8028 file = CreateFileW( prop_guid_path.wszPath, FILE_READ_ACCESS | FILE_WRITE_ACCESS,
8029 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
8030 FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING, NULL );
8031 ok( file != INVALID_HANDLE_VALUE, "got error %u\n", GetLastError() );
8033 hwnd = CreateWindowW( L"static", L"dinput", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 10, 10, 200, 200,
8034 NULL, NULL, NULL, NULL );
8036 hr = IDirectInputDevice8_SetCooperativeLevel( device, hwnd, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE );
8037 ok( hr == DI_OK, "SetCooperativeLevel returned: %#x\n", hr );
8039 prop_dword.diph.dwHow = DIPH_BYUSAGE;
8040 prop_dword.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC );
8041 prop_dword.dwData = DIPROPAUTOCENTER_ON;
8042 hr = IDirectInputDevice8_SetProperty( device, DIPROP_AUTOCENTER, &prop_dword.diph );
8043 ok( hr == DIERR_UNSUPPORTED, "SetProperty DIPROP_AUTOCENTER returned %#x\n", hr );
8044 prop_dword.diph.dwHow = DIPH_DEVICE;
8045 prop_dword.diph.dwObj = 0;
8046 hr = IDirectInputDevice8_SetProperty( device, DIPROP_AUTOCENTER, &prop_dword.diph );
8047 ok( hr == DI_OK, "SetProperty DIPROP_AUTOCENTER returned %#x\n", hr );
8049 hr = IDirectInputDevice8_Acquire( device );
8050 ok( hr == DI_OK, "Acquire returned: %#x\n", hr );
8052 prop_dword.dwData = 0xdeadbeef;
8053 hr = IDirectInputDevice8_SetProperty( device, DIPROP_FFGAIN, &prop_dword.diph );
8054 ok( hr == DIERR_INVALIDPARAM, "SetProperty DIPROP_FFGAIN returned %#x\n", hr );
8055 prop_dword.dwData = 1000;
8056 hr = IDirectInputDevice8_SetProperty( device, DIPROP_FFGAIN, &prop_dword.diph );
8057 ok( hr == DI_OK, "SetProperty DIPROP_FFGAIN returned %#x\n", hr );
8059 prop_dword.dwData = 0xdeadbeef;
8060 hr = IDirectInputDevice8_SetProperty( device, DIPROP_FFLOAD, &prop_dword.diph );
8061 ok( hr == DIERR_READONLY, "SetProperty DIPROP_FFLOAD returned %#x\n", hr );
8062 hr = IDirectInputDevice8_GetProperty( device, DIPROP_FFLOAD, &prop_dword.diph );
8063 ok( hr == DIERR_NOTEXCLUSIVEACQUIRED, "GetProperty DIPROP_FFLOAD returned %#x\n", hr );
8064 hr = IDirectInputDevice8_GetForceFeedbackState( device, &res );
8065 todo_wine
8066 ok( hr == DIERR_NOTEXCLUSIVEACQUIRED, "GetForceFeedbackState returned %#x\n", hr );
8067 hr = IDirectInputDevice8_SendForceFeedbackCommand( device, DISFFC_RESET );
8068 ok( hr == DIERR_NOTEXCLUSIVEACQUIRED, "SendForceFeedbackCommand returned %#x\n", hr );
8070 escape.dwSize = sizeof(DIEFFESCAPE);
8071 escape.dwCommand = 0;
8072 escape.lpvInBuffer = buffer;
8073 escape.cbInBuffer = 10;
8074 escape.lpvOutBuffer = buffer + 10;
8075 escape.cbOutBuffer = 10;
8076 hr = IDirectInputDevice8_Escape( device, &escape );
8077 todo_wine
8078 ok( hr == DIERR_NOTEXCLUSIVEACQUIRED, "Escape returned: %#x\n", hr );
8080 hr = IDirectInputDevice8_Unacquire( device );
8081 ok( hr == DI_OK, "Unacquire returned: %#x\n", hr );
8082 hr = IDirectInputDevice8_SetCooperativeLevel( device, hwnd, DISCL_BACKGROUND | DISCL_EXCLUSIVE );
8083 ok( hr == DI_OK, "SetCooperativeLevel returned: %#x\n", hr );
8085 set_hid_expect( file, expect_acquire, sizeof(expect_acquire) );
8086 hr = IDirectInputDevice8_Acquire( device );
8087 ok( hr == DI_OK, "Acquire returned: %#x\n", hr );
8088 wait_hid_expect( file, 100 ); /* device gain reports are written asynchronously */
8090 set_hid_expect( file, &expect_set_device_gain_2, sizeof(expect_set_device_gain_2) );
8091 prop_dword.dwData = 2000;
8092 hr = IDirectInputDevice8_SetProperty( device, DIPROP_FFGAIN, &prop_dword.diph );
8093 ok( hr == DI_OK, "SetProperty DIPROP_FFGAIN returned %#x\n", hr );
8094 wait_hid_expect( file, 100 ); /* device gain reports are written asynchronously */
8096 set_hid_expect( file, &expect_set_device_gain_1, sizeof(expect_set_device_gain_1) );
8097 prop_dword.dwData = 1000;
8098 hr = IDirectInputDevice8_SetProperty( device, DIPROP_FFGAIN, &prop_dword.diph );
8099 ok( hr == DI_OK, "SetProperty DIPROP_FFGAIN returned %#x\n", hr );
8100 wait_hid_expect( file, 100 ); /* device gain reports are written asynchronously */
8102 hr = IDirectInputDevice8_Escape( device, &escape );
8103 todo_wine
8104 ok( hr == DIERR_UNSUPPORTED, "Escape returned: %#x\n", hr );
8106 prop_dword.dwData = 0xdeadbeef;
8107 hr = IDirectInputDevice8_GetProperty( device, DIPROP_FFLOAD, &prop_dword.diph );
8108 todo_wine
8109 ok( hr == 0x80040301, "GetProperty DIPROP_FFLOAD returned %#x\n", hr );
8110 res = 0xdeadbeef;
8111 hr = IDirectInputDevice8_GetForceFeedbackState( device, &res );
8112 todo_wine
8113 ok( hr == 0x80040301, "GetForceFeedbackState returned %#x\n", hr );
8115 hr = IDirectInputDevice8_SendForceFeedbackCommand( device, 0xdeadbeef );
8116 ok( hr == DIERR_INVALIDPARAM, "SendForceFeedbackCommand returned %#x\n", hr );
8118 set_hid_expect( file, expect_acquire, sizeof(expect_acquire) );
8119 hr = IDirectInputDevice8_SendForceFeedbackCommand( device, DISFFC_RESET );
8120 ok( hr == DI_OK, "SendForceFeedbackCommand returned %#x\n", hr );
8121 wait_hid_expect( file, 100 ); /* device gain reports are written asynchronously */
8123 hr = IDirectInputDevice8_SendForceFeedbackCommand( device, DISFFC_STOPALL );
8124 ok( hr == HIDP_STATUS_USAGE_NOT_FOUND, "SendForceFeedbackCommand returned %#x\n", hr );
8125 hr = IDirectInputDevice8_SendForceFeedbackCommand( device, DISFFC_PAUSE );
8126 ok( hr == HIDP_STATUS_USAGE_NOT_FOUND, "SendForceFeedbackCommand returned %#x\n", hr );
8127 hr = IDirectInputDevice8_SendForceFeedbackCommand( device, DISFFC_CONTINUE );
8128 ok( hr == HIDP_STATUS_USAGE_NOT_FOUND, "SendForceFeedbackCommand returned %#x\n", hr );
8129 hr = IDirectInputDevice8_SendForceFeedbackCommand( device, DISFFC_SETACTUATORSON );
8130 ok( hr == HIDP_STATUS_USAGE_NOT_FOUND, "SendForceFeedbackCommand returned %#x\n", hr );
8131 hr = IDirectInputDevice8_SendForceFeedbackCommand( device, DISFFC_SETACTUATORSOFF );
8132 ok( hr == HIDP_STATUS_USAGE_NOT_FOUND, "SendForceFeedbackCommand returned %#x\n", hr );
8134 objdata.dwOfs = 0x1e;
8135 objdata.dwData = 0x80;
8136 res = 1;
8137 hr = IDirectInputDevice8_SendDeviceData( device, sizeof(DIDEVICEOBJECTDATA), &objdata, &res, 0 );
8138 if (version < 0x800) ok( hr == DI_OK, "SendDeviceData returned %#x\n", hr );
8139 else todo_wine ok( hr == DIERR_INVALIDPARAM, "SendDeviceData returned %#x\n", hr );
8141 test_periodic_effect( device, file, version );
8142 test_condition_effect( device, file, version );
8144 set_hid_expect( file, expect_reset, sizeof(expect_reset) );
8145 hr = IDirectInputDevice8_Unacquire( device );
8146 ok( hr == DI_OK, "Unacquire returned: %#x\n", hr );
8147 set_hid_expect( file, NULL, 0 );
8149 ref = IDirectInputDevice8_Release( device );
8150 ok( ref == 0, "Release returned %d\n", ref );
8152 DestroyWindow( hwnd );
8153 CloseHandle( file );
8155 done:
8156 pnp_driver_stop();
8157 cleanup_registry_keys();
8158 SetCurrentDirectoryW( cwd );
8159 winetest_pop_context();
8162 static void test_device_managed_effect(void)
8164 #include "psh_hid_macros.h"
8165 const unsigned char report_descriptor[] = {
8166 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
8167 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
8168 COLLECTION(1, Application),
8169 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
8170 COLLECTION(1, Report),
8171 REPORT_ID(1, 1),
8173 USAGE(1, HID_USAGE_GENERIC_X),
8174 USAGE(1, HID_USAGE_GENERIC_Y),
8175 USAGE(1, HID_USAGE_GENERIC_Z),
8176 LOGICAL_MINIMUM(1, 0),
8177 LOGICAL_MAXIMUM(1, 0x7f),
8178 PHYSICAL_MINIMUM(1, 0),
8179 PHYSICAL_MAXIMUM(1, 0x7f),
8180 REPORT_SIZE(1, 8),
8181 REPORT_COUNT(1, 3),
8182 INPUT(1, Data|Var|Abs),
8184 USAGE_PAGE(1, HID_USAGE_PAGE_BUTTON),
8185 USAGE_MINIMUM(1, 1),
8186 USAGE_MAXIMUM(1, 2),
8187 LOGICAL_MINIMUM(1, 0),
8188 LOGICAL_MAXIMUM(1, 1),
8189 PHYSICAL_MINIMUM(1, 0),
8190 PHYSICAL_MAXIMUM(1, 1),
8191 REPORT_SIZE(1, 1),
8192 REPORT_COUNT(1, 2),
8193 INPUT(1, Data|Var|Abs),
8194 REPORT_COUNT(1, 6),
8195 INPUT(1, Cnst|Var|Abs),
8196 END_COLLECTION,
8198 USAGE_PAGE(1, HID_USAGE_PAGE_PID),
8199 USAGE(1, PID_USAGE_STATE_REPORT),
8200 COLLECTION(1, Report),
8201 REPORT_ID(1, 2),
8203 USAGE(1, PID_USAGE_DEVICE_PAUSED),
8204 USAGE(1, PID_USAGE_ACTUATORS_ENABLED),
8205 USAGE(1, PID_USAGE_SAFETY_SWITCH),
8206 USAGE(1, PID_USAGE_ACTUATOR_OVERRIDE_SWITCH),
8207 USAGE(1, PID_USAGE_ACTUATOR_POWER),
8208 LOGICAL_MINIMUM(1, 0),
8209 LOGICAL_MAXIMUM(1, 1),
8210 PHYSICAL_MINIMUM(1, 0),
8211 PHYSICAL_MAXIMUM(1, 1),
8212 REPORT_SIZE(1, 1),
8213 REPORT_COUNT(1, 5),
8214 INPUT(1, Data|Var|Abs),
8215 REPORT_COUNT(1, 3),
8216 INPUT(1, Cnst|Var|Abs),
8218 USAGE(1, PID_USAGE_EFFECT_PLAYING),
8219 LOGICAL_MINIMUM(1, 0),
8220 LOGICAL_MAXIMUM(1, 1),
8221 PHYSICAL_MINIMUM(1, 0),
8222 PHYSICAL_MAXIMUM(1, 1),
8223 REPORT_SIZE(1, 1),
8224 REPORT_COUNT(1, 8),
8225 INPUT(1, Data|Var|Abs),
8227 USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX),
8228 LOGICAL_MINIMUM(1, 1),
8229 LOGICAL_MAXIMUM(1, 0x7f),
8230 PHYSICAL_MINIMUM(1, 1),
8231 PHYSICAL_MAXIMUM(1, 0x7f),
8232 REPORT_SIZE(1, 8),
8233 REPORT_COUNT(1, 1),
8234 INPUT(1, Data|Var|Abs),
8235 END_COLLECTION,
8237 USAGE_PAGE(1, HID_USAGE_PAGE_PID),
8238 USAGE(1, PID_USAGE_DEVICE_CONTROL_REPORT),
8239 COLLECTION(1, Report),
8240 REPORT_ID(1, 1),
8242 USAGE(1, PID_USAGE_DEVICE_CONTROL),
8243 COLLECTION(1, Logical),
8244 USAGE(1, PID_USAGE_DC_DEVICE_RESET),
8245 LOGICAL_MINIMUM(1, 1),
8246 LOGICAL_MAXIMUM(1, 2),
8247 PHYSICAL_MINIMUM(1, 1),
8248 PHYSICAL_MAXIMUM(1, 2),
8249 REPORT_SIZE(1, 8),
8250 REPORT_COUNT(1, 1),
8251 OUTPUT(1, Data|Ary|Abs),
8252 END_COLLECTION,
8253 END_COLLECTION,
8255 USAGE(1, PID_USAGE_EFFECT_OPERATION_REPORT),
8256 COLLECTION(1, Report),
8257 REPORT_ID(1, 2),
8259 USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX),
8260 LOGICAL_MINIMUM(1, 1),
8261 LOGICAL_MAXIMUM(1, 0x7f),
8262 PHYSICAL_MINIMUM(1, 1),
8263 PHYSICAL_MAXIMUM(1, 0x7f),
8264 REPORT_SIZE(1, 8),
8265 REPORT_COUNT(1, 1),
8266 OUTPUT(1, Data|Var|Abs),
8268 USAGE(1, PID_USAGE_EFFECT_OPERATION),
8269 COLLECTION(1, NamedArray),
8270 USAGE(1, PID_USAGE_OP_EFFECT_START),
8271 USAGE(1, PID_USAGE_OP_EFFECT_START_SOLO),
8272 USAGE(1, PID_USAGE_OP_EFFECT_STOP),
8273 LOGICAL_MINIMUM(1, 1),
8274 LOGICAL_MAXIMUM(1, 3),
8275 PHYSICAL_MINIMUM(1, 1),
8276 PHYSICAL_MAXIMUM(1, 3),
8277 REPORT_SIZE(1, 8),
8278 REPORT_COUNT(1, 1),
8279 OUTPUT(1, Data|Ary|Abs),
8280 END_COLLECTION,
8282 USAGE(1, PID_USAGE_LOOP_COUNT),
8283 LOGICAL_MINIMUM(1, 0),
8284 LOGICAL_MAXIMUM(1, 0x7f),
8285 PHYSICAL_MINIMUM(1, 0),
8286 PHYSICAL_MAXIMUM(1, 0x7f),
8287 REPORT_SIZE(1, 8),
8288 REPORT_COUNT(1, 1),
8289 OUTPUT(1, Data|Var|Abs),
8290 END_COLLECTION,
8292 USAGE(1, PID_USAGE_SET_EFFECT_REPORT),
8293 COLLECTION(1, Report),
8294 REPORT_ID(1, 3),
8296 USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX),
8297 LOGICAL_MINIMUM(1, 1),
8298 LOGICAL_MAXIMUM(1, 0x7f),
8299 PHYSICAL_MINIMUM(1, 1),
8300 PHYSICAL_MAXIMUM(1, 0x7f),
8301 REPORT_SIZE(1, 8),
8302 REPORT_COUNT(1, 1),
8303 OUTPUT(1, Data|Var|Abs),
8305 USAGE(1, PID_USAGE_EFFECT_TYPE),
8306 COLLECTION(1, NamedArray),
8307 USAGE(1, PID_USAGE_ET_SQUARE),
8308 USAGE(1, PID_USAGE_ET_SINE),
8309 USAGE(1, PID_USAGE_ET_SPRING),
8310 LOGICAL_MINIMUM(1, 1),
8311 LOGICAL_MAXIMUM(1, 3),
8312 PHYSICAL_MINIMUM(1, 1),
8313 PHYSICAL_MAXIMUM(1, 3),
8314 REPORT_SIZE(1, 8),
8315 REPORT_COUNT(1, 1),
8316 OUTPUT(1, Data|Ary|Abs),
8317 END_COLLECTION,
8319 USAGE(1, PID_USAGE_AXES_ENABLE),
8320 COLLECTION(1, Logical),
8321 USAGE(4, (HID_USAGE_PAGE_GENERIC << 16)|HID_USAGE_GENERIC_X),
8322 USAGE(4, (HID_USAGE_PAGE_GENERIC << 16)|HID_USAGE_GENERIC_Y),
8323 USAGE(4, (HID_USAGE_PAGE_GENERIC << 16)|HID_USAGE_GENERIC_Z),
8324 LOGICAL_MINIMUM(1, 0),
8325 LOGICAL_MAXIMUM(1, 1),
8326 PHYSICAL_MINIMUM(1, 0),
8327 PHYSICAL_MAXIMUM(1, 1),
8328 REPORT_SIZE(1, 1),
8329 REPORT_COUNT(1, 3),
8330 OUTPUT(1, Data|Var|Abs),
8331 END_COLLECTION,
8332 USAGE(1, PID_USAGE_DIRECTION_ENABLE),
8333 REPORT_COUNT(1, 1),
8334 OUTPUT(1, Data|Var|Abs),
8335 REPORT_COUNT(1, 4),
8336 OUTPUT(1, Cnst|Var|Abs),
8338 USAGE(1, PID_USAGE_DURATION),
8339 USAGE(1, PID_USAGE_START_DELAY),
8340 UNIT(2, 0x1003), /* Eng Lin:Time */
8341 UNIT_EXPONENT(1, -3), /* 10^-3 */
8342 LOGICAL_MINIMUM(1, 0),
8343 LOGICAL_MAXIMUM(2, 0x7fff),
8344 PHYSICAL_MINIMUM(1, 0),
8345 PHYSICAL_MAXIMUM(2, 0x7fff),
8346 REPORT_SIZE(1, 16),
8347 REPORT_COUNT(1, 2),
8348 OUTPUT(1, Data|Var|Abs),
8349 UNIT(1, 0),
8350 UNIT_EXPONENT(1, 0),
8352 USAGE(1, PID_USAGE_TRIGGER_BUTTON),
8353 LOGICAL_MINIMUM(1, 1),
8354 LOGICAL_MAXIMUM(1, 0x08),
8355 PHYSICAL_MINIMUM(1, 1),
8356 PHYSICAL_MAXIMUM(1, 0x08),
8357 REPORT_SIZE(1, 8),
8358 REPORT_COUNT(1, 1),
8359 OUTPUT(1, Data|Var|Abs),
8361 USAGE(1, PID_USAGE_DIRECTION),
8362 COLLECTION(1, Logical),
8363 USAGE(4, (HID_USAGE_PAGE_ORDINAL << 16)|1),
8364 USAGE(4, (HID_USAGE_PAGE_ORDINAL << 16)|2),
8365 UNIT(1, 0x14), /* Eng Rot:Angular Pos */
8366 UNIT_EXPONENT(1, -2), /* 10^-2 */
8367 LOGICAL_MINIMUM(1, 0),
8368 LOGICAL_MAXIMUM(2, 0x00ff),
8369 PHYSICAL_MINIMUM(1, 0),
8370 PHYSICAL_MAXIMUM(4, 0x00008ca0),
8371 UNIT(1, 0),
8372 REPORT_SIZE(1, 8),
8373 REPORT_COUNT(1, 2),
8374 OUTPUT(1, Data|Var|Abs),
8375 UNIT_EXPONENT(1, 0),
8376 UNIT(1, 0),
8377 END_COLLECTION,
8378 END_COLLECTION,
8380 USAGE(1, PID_USAGE_SET_CONDITION_REPORT),
8381 COLLECTION(1, Logical),
8382 REPORT_ID(1, 4),
8384 USAGE(1, PID_USAGE_TYPE_SPECIFIC_BLOCK_OFFSET),
8385 COLLECTION(1, Logical),
8386 USAGE(4, (HID_USAGE_PAGE_ORDINAL << 16)|1),
8387 USAGE(4, (HID_USAGE_PAGE_ORDINAL << 16)|2),
8388 LOGICAL_MINIMUM(1, 0),
8389 LOGICAL_MAXIMUM(1, 1),
8390 PHYSICAL_MINIMUM(1, 0),
8391 PHYSICAL_MAXIMUM(1, 1),
8392 REPORT_SIZE(1, 2),
8393 REPORT_COUNT(1, 2),
8394 OUTPUT(1, Data|Var|Abs),
8395 END_COLLECTION,
8396 REPORT_SIZE(1, 4),
8397 REPORT_COUNT(1, 1),
8398 OUTPUT(1, Cnst|Var|Abs),
8400 USAGE(1, PID_USAGE_CP_OFFSET),
8401 LOGICAL_MINIMUM(1, 0x80),
8402 LOGICAL_MAXIMUM(1, 0x7f),
8403 PHYSICAL_MINIMUM(2, 0xd8f0),
8404 PHYSICAL_MAXIMUM(2, 0x2710),
8405 REPORT_SIZE(1, 8),
8406 REPORT_COUNT(1, 1),
8407 OUTPUT(1, Data|Var|Abs),
8409 USAGE(1, PID_USAGE_POSITIVE_COEFFICIENT),
8410 USAGE(1, PID_USAGE_NEGATIVE_COEFFICIENT),
8411 LOGICAL_MINIMUM(1, 0x80),
8412 LOGICAL_MAXIMUM(1, 0x7f),
8413 PHYSICAL_MINIMUM(2, 0xd8f0),
8414 PHYSICAL_MAXIMUM(2, 0x2710),
8415 REPORT_SIZE(1, 8),
8416 REPORT_COUNT(1, 2),
8417 OUTPUT(1, Data|Var|Abs),
8419 USAGE(1, PID_USAGE_POSITIVE_SATURATION),
8420 USAGE(1, PID_USAGE_NEGATIVE_SATURATION),
8421 LOGICAL_MINIMUM(1, 0),
8422 LOGICAL_MAXIMUM(2, 0x00ff),
8423 PHYSICAL_MINIMUM(1, 0),
8424 PHYSICAL_MAXIMUM(2, 0x2710),
8425 REPORT_SIZE(1, 8),
8426 REPORT_COUNT(1, 2),
8427 OUTPUT(1, Data|Var|Abs),
8429 USAGE(1, PID_USAGE_DEAD_BAND),
8430 LOGICAL_MINIMUM(1, 0),
8431 LOGICAL_MAXIMUM(2, 0x00ff),
8432 PHYSICAL_MINIMUM(1, 0),
8433 PHYSICAL_MAXIMUM(2, 0x2710),
8434 REPORT_SIZE(1, 8),
8435 REPORT_COUNT(1, 1),
8436 OUTPUT(1, Data|Var|Abs),
8437 END_COLLECTION,
8439 USAGE(1, PID_USAGE_BLOCK_FREE_REPORT),
8440 COLLECTION(1, Logical),
8441 REPORT_ID(1, 5),
8443 USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX),
8444 LOGICAL_MINIMUM(1, 1),
8445 LOGICAL_MAXIMUM(1, 0x7f),
8446 PHYSICAL_MINIMUM(1, 1),
8447 PHYSICAL_MAXIMUM(1, 0x7f),
8448 REPORT_SIZE(1, 8),
8449 REPORT_COUNT(1, 1),
8450 OUTPUT(1, Data|Var|Abs),
8451 END_COLLECTION,
8453 USAGE(1, PID_USAGE_POOL_REPORT),
8454 COLLECTION(1, Logical),
8455 REPORT_ID(1, 1),
8457 USAGE(1, PID_USAGE_RAM_POOL_SIZE),
8458 LOGICAL_MINIMUM(1, 0),
8459 LOGICAL_MAXIMUM(4, 0xffff),
8460 PHYSICAL_MINIMUM(1, 0),
8461 PHYSICAL_MAXIMUM(4, 0xffff),
8462 REPORT_SIZE(1, 16),
8463 REPORT_COUNT(1, 1),
8464 FEATURE(1, Data|Var|Abs),
8466 USAGE(1, PID_USAGE_SIMULTANEOUS_EFFECTS_MAX),
8467 LOGICAL_MINIMUM(1, 0),
8468 LOGICAL_MAXIMUM(1, 0x7f),
8469 PHYSICAL_MINIMUM(1, 0),
8470 PHYSICAL_MAXIMUM(1, 0x7f),
8471 REPORT_SIZE(1, 8),
8472 REPORT_COUNT(1, 1),
8473 FEATURE(1, Data|Var|Abs),
8475 USAGE(1, PID_USAGE_DEVICE_MANAGED_POOL),
8476 USAGE(1, PID_USAGE_SHARED_PARAMETER_BLOCKS),
8477 LOGICAL_MINIMUM(1, 0),
8478 LOGICAL_MAXIMUM(1, 1),
8479 PHYSICAL_MINIMUM(1, 0),
8480 PHYSICAL_MAXIMUM(1, 1),
8481 REPORT_SIZE(1, 1),
8482 REPORT_COUNT(1, 8),
8483 FEATURE(1, Data|Var|Abs),
8484 END_COLLECTION,
8486 USAGE(1, PID_USAGE_CREATE_NEW_EFFECT_REPORT),
8487 COLLECTION(1, Logical),
8488 REPORT_ID(1, 2),
8490 USAGE(1, PID_USAGE_EFFECT_TYPE),
8491 COLLECTION(1, NamedArray),
8492 USAGE(1, PID_USAGE_ET_SQUARE),
8493 USAGE(1, PID_USAGE_ET_SINE),
8494 USAGE(1, PID_USAGE_ET_SPRING),
8495 LOGICAL_MINIMUM(1, 1),
8496 LOGICAL_MAXIMUM(1, 3),
8497 PHYSICAL_MINIMUM(1, 1),
8498 PHYSICAL_MAXIMUM(1, 3),
8499 REPORT_SIZE(1, 8),
8500 REPORT_COUNT(1, 1),
8501 FEATURE(1, Data|Ary|Abs),
8502 END_COLLECTION,
8503 END_COLLECTION,
8505 USAGE(1, PID_USAGE_BLOCK_LOAD_REPORT),
8506 COLLECTION(1, Logical),
8507 REPORT_ID(1, 3),
8509 USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX),
8510 LOGICAL_MINIMUM(1, 1),
8511 LOGICAL_MAXIMUM(1, 0x7f),
8512 PHYSICAL_MINIMUM(1, 1),
8513 PHYSICAL_MAXIMUM(1, 0x7f),
8514 REPORT_SIZE(1, 8),
8515 REPORT_COUNT(1, 1),
8516 FEATURE(1, Data|Var|Abs),
8518 USAGE(1, PID_USAGE_BLOCK_LOAD_STATUS),
8519 COLLECTION(1, NamedArray),
8520 USAGE(1, PID_USAGE_BLOCK_LOAD_SUCCESS),
8521 USAGE(1, PID_USAGE_BLOCK_LOAD_FULL),
8522 USAGE(1, PID_USAGE_BLOCK_LOAD_ERROR),
8523 LOGICAL_MINIMUM(1, 1),
8524 LOGICAL_MAXIMUM(1, 3),
8525 PHYSICAL_MINIMUM(1, 1),
8526 PHYSICAL_MAXIMUM(1, 3),
8527 REPORT_SIZE(1, 8),
8528 REPORT_COUNT(1, 1),
8529 FEATURE(1, Data|Ary|Abs),
8530 END_COLLECTION,
8532 USAGE(1, PID_USAGE_RAM_POOL_AVAILABLE),
8533 LOGICAL_MINIMUM(1, 0),
8534 LOGICAL_MAXIMUM(4, 0xffff),
8535 PHYSICAL_MINIMUM(1, 0),
8536 PHYSICAL_MAXIMUM(4, 0xffff),
8537 REPORT_SIZE(1, 1),
8538 REPORT_COUNT(1, 16),
8539 FEATURE(1, Data|Var|Abs),
8540 END_COLLECTION,
8541 END_COLLECTION,
8543 #include "pop_hid_macros.h"
8545 static const HIDP_CAPS hid_caps =
8547 .InputReportByteLength = 5,
8549 struct hid_expect expect_reset[] =
8551 /* device reset */
8553 .code = IOCTL_HID_WRITE_REPORT,
8554 .report_id = 1,
8555 .report_len = 2,
8556 .report_buf = {1, 0x01},
8559 struct hid_expect expect_create[] =
8561 /* create new effect */
8563 .code = IOCTL_HID_SET_FEATURE,
8564 .report_id = 2,
8565 .report_len = 2,
8566 .report_buf = {2,0x03},
8568 /* block load */
8570 .code = IOCTL_HID_GET_FEATURE,
8571 .report_id = 3,
8572 .report_len = 5,
8573 .report_buf = {3,0x01,0x01,0x00,0x00},
8575 /* set condition */
8577 .code = IOCTL_HID_WRITE_REPORT,
8578 .report_id = 4,
8579 .report_len = 8,
8580 .report_buf = {4,0x00,0xf9,0x19,0xd9,0xff,0xff,0x99},
8582 /* set condition */
8584 .code = IOCTL_HID_WRITE_REPORT,
8585 .report_id = 4,
8586 .report_len = 8,
8587 .report_buf = {4,0x00,0x4c,0x3f,0xcc,0x4c,0x33,0x19},
8589 /* update effect */
8591 .code = IOCTL_HID_WRITE_REPORT,
8592 .report_id = 3,
8593 .report_len = 11,
8594 .report_buf = {3,0x01,0x03,0x08,0x01,0x00,0x06,0x00,0x01,0x55,0x00},
8597 struct hid_expect expect_start =
8599 /* effect control */
8600 .code = IOCTL_HID_WRITE_REPORT,
8601 .report_id = 2,
8602 .report_len = 4,
8603 .report_buf = {2,0x01,0x01,0x01},
8605 struct hid_expect expect_stop =
8607 /* effect control */
8608 .code = IOCTL_HID_WRITE_REPORT,
8609 .report_id = 2,
8610 .report_len = 4,
8611 .report_buf = {2,0x01,0x03,0x00},
8613 struct hid_expect expect_destroy[] =
8615 /* effect operation */
8617 .code = IOCTL_HID_WRITE_REPORT,
8618 .report_id = 2,
8619 .report_len = 4,
8620 .report_buf = {2,0x01,0x03,0x00},
8622 /* block free */
8624 .code = IOCTL_HID_WRITE_REPORT,
8625 .report_id = 5,
8626 .report_len = 2,
8627 .report_buf = {5,0x01},
8630 struct hid_expect device_state_input[] =
8632 /* effect state */
8634 .code = IOCTL_HID_READ_REPORT,
8635 .report_id = 2,
8636 .report_len = 4,
8637 .report_buf = {2,0xff,0x00,0xff},
8639 /* device state */
8641 .code = IOCTL_HID_READ_REPORT,
8642 .report_id = 1,
8643 .report_len = 5,
8644 .report_buf = {1,0x12,0x34,0x56,0xff},
8647 struct hid_expect device_state_input_1[] =
8649 /* effect state */
8651 .code = IOCTL_HID_READ_REPORT,
8652 .report_id = 2,
8653 .report_len = 4,
8654 .report_buf = {2,0x00,0x01,0x00},
8656 /* device state */
8658 .code = IOCTL_HID_READ_REPORT,
8659 .report_id = 1,
8660 .report_len = 5,
8661 .report_buf = {1,0x65,0x43,0x21,0x00},
8664 struct hid_expect device_state_input_2[] =
8666 /* effect state */
8668 .code = IOCTL_HID_READ_REPORT,
8669 .report_id = 2,
8670 .report_len = 4,
8671 .report_buf = {2,0x03,0x00,0x00},
8673 /* device state */
8675 .code = IOCTL_HID_READ_REPORT,
8676 .report_id = 1,
8677 .report_len = 5,
8678 .report_buf = {1,0x12,0x34,0x56,0xff},
8681 struct hid_expect expect_pool[] =
8683 /* device pool */
8685 .code = IOCTL_HID_GET_FEATURE,
8686 .report_id = 1,
8687 .report_len = 5,
8688 .report_buf = {1,0x10,0x00,0x01,0x03},
8689 .todo = TRUE,
8691 /* device pool */
8693 .code = IOCTL_HID_GET_FEATURE,
8694 .report_id = 1,
8695 .report_len = 5,
8696 .report_buf = {1,0x10,0x00,0x01,0x03},
8697 .todo = TRUE,
8700 static const DWORD expect_axes[3] =
8702 DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 0 ) | DIDFT_FFACTUATOR,
8703 DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 2 ) | DIDFT_FFACTUATOR,
8704 DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 1 ) | DIDFT_FFACTUATOR,
8706 static const LONG expect_directions[3] = {
8707 +3000,
8711 static const DIENVELOPE expect_envelope =
8713 .dwSize = sizeof(DIENVELOPE),
8714 .dwAttackLevel = 1000,
8715 .dwAttackTime = 2000,
8716 .dwFadeLevel = 3000,
8717 .dwFadeTime = 4000,
8719 static const DICONDITION expect_condition[3] =
8722 .lOffset = -500,
8723 .lPositiveCoefficient = 2000,
8724 .lNegativeCoefficient = -3000,
8725 .dwPositiveSaturation = -4000,
8726 .dwNegativeSaturation = -5000,
8727 .lDeadBand = 6000,
8730 .lOffset = 6000,
8731 .lPositiveCoefficient = 5000,
8732 .lNegativeCoefficient = -4000,
8733 .dwPositiveSaturation = 3000,
8734 .dwNegativeSaturation = 2000,
8735 .lDeadBand = 1000,
8738 .lOffset = -7000,
8739 .lPositiveCoefficient = -8000,
8740 .lNegativeCoefficient = 9000,
8741 .dwPositiveSaturation = 10000,
8742 .dwNegativeSaturation = 11000,
8743 .lDeadBand = -12000,
8746 const DIEFFECT expect_desc =
8748 .dwSize = sizeof(DIEFFECT_DX6),
8749 .dwFlags = DIEFF_SPHERICAL | DIEFF_OBJECTIDS,
8750 .dwDuration = 1000,
8751 .dwSamplePeriod = 2000,
8752 .dwGain = 3000,
8753 .dwTriggerButton = DIDFT_PSHBUTTON | DIDFT_MAKEINSTANCE( 0 ) | DIDFT_FFEFFECTTRIGGER,
8754 .dwTriggerRepeatInterval = 5000,
8755 .cAxes = 2,
8756 .rgdwAxes = (void *)expect_axes,
8757 .rglDirection = (void *)expect_directions,
8758 .lpEnvelope = (void *)&expect_envelope,
8759 .cbTypeSpecificParams = 2 * sizeof(DICONDITION),
8760 .lpvTypeSpecificParams = (void *)expect_condition,
8761 .dwStartDelay = 6000,
8763 DIPROPGUIDANDPATH prop_guid_path =
8765 .diph =
8767 .dwSize = sizeof(DIPROPGUIDANDPATH),
8768 .dwHeaderSize = sizeof(DIPROPHEADER),
8769 .dwHow = DIPH_DEVICE,
8772 DIPROPDWORD prop_dword =
8774 .diph =
8776 .dwSize = sizeof(DIPROPDWORD),
8777 .dwHeaderSize = sizeof(DIPROPHEADER),
8778 .dwHow = DIPH_DEVICE,
8781 DIDEVICEINSTANCEW devinst = {.dwSize = sizeof(DIDEVICEINSTANCEW)};
8782 WCHAR cwd[MAX_PATH], tempdir[MAX_PATH];
8783 IDirectInputDevice8W *device;
8784 IDirectInputEffect *effect;
8785 HANDLE file, event;
8786 ULONG res, ref;
8787 DWORD flags;
8788 HRESULT hr;
8789 HWND hwnd;
8791 GetCurrentDirectoryW( ARRAY_SIZE(cwd), cwd );
8792 GetTempPathW( ARRAY_SIZE(tempdir), tempdir );
8793 SetCurrentDirectoryW( tempdir );
8795 cleanup_registry_keys();
8796 if (!dinput_driver_start( report_descriptor, sizeof(report_descriptor), &hid_caps,
8797 expect_pool, sizeof(expect_pool) )) goto done;
8798 if (FAILED(hr = create_dinput_device( DIRECTINPUT_VERSION, &devinst, &device ))) goto done;
8800 hr = IDirectInputDevice8_GetProperty( device, DIPROP_GUIDANDPATH, &prop_guid_path.diph );
8801 ok( hr == DI_OK, "GetProperty DIPROP_GUIDANDPATH returned %#x\n", hr );
8802 file = CreateFileW( prop_guid_path.wszPath, FILE_READ_ACCESS | FILE_WRITE_ACCESS,
8803 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
8804 FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING, NULL );
8805 ok( file != INVALID_HANDLE_VALUE, "got error %u\n", GetLastError() );
8807 hwnd = CreateWindowW( L"static", L"dinput", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 10, 10, 200, 200,
8808 NULL, NULL, NULL, NULL );
8810 event = CreateEventW( NULL, FALSE, FALSE, NULL );
8811 ok( event != NULL, "CreateEventW failed, last error %u\n", GetLastError() );
8812 hr = IDirectInputDevice8_SetEventNotification( device, event );
8813 ok( hr == DI_OK, "SetEventNotification returned: %#x\n", hr );
8814 hr = IDirectInputDevice8_SetCooperativeLevel( device, hwnd, DISCL_BACKGROUND | DISCL_EXCLUSIVE );
8815 ok( hr == DI_OK, "SetCooperativeLevel returned: %#x\n", hr );
8816 hr = IDirectInputDevice8_SetDataFormat( device, &c_dfDIJoystick2 );
8817 ok( hr == DI_OK, "SetDataFormat returned: %#x\n", hr );
8819 hr = IDirectInputDevice8_GetProperty( device, DIPROP_FFLOAD, &prop_dword.diph );
8820 ok( hr == DIERR_NOTEXCLUSIVEACQUIRED, "GetProperty DIPROP_FFLOAD returned %#x\n", hr );
8821 hr = IDirectInputDevice8_GetForceFeedbackState( device, &res );
8822 todo_wine
8823 ok( hr == DIERR_NOTEXCLUSIVEACQUIRED, "GetForceFeedbackState returned %#x\n", hr );
8824 hr = IDirectInputDevice8_SendForceFeedbackCommand( device, DISFFC_RESET );
8825 ok( hr == DIERR_NOTEXCLUSIVEACQUIRED, "SendForceFeedbackCommand returned %#x\n", hr );
8827 set_hid_expect( file, expect_reset, sizeof(expect_reset) );
8828 hr = IDirectInputDevice8_Acquire( device );
8829 ok( hr == DI_OK, "Acquire returned: %#x\n", hr );
8830 wait_hid_expect( file, 100 );
8832 set_hid_expect( file, expect_pool, sizeof(struct hid_expect) );
8833 prop_dword.dwData = 0xdeadbeef;
8834 hr = IDirectInputDevice8_GetProperty( device, DIPROP_FFLOAD, &prop_dword.diph );
8835 ok( hr == DI_OK, "GetProperty DIPROP_FFLOAD returned %#x\n", hr );
8836 ok( prop_dword.dwData == 0, "got DIPROP_FFLOAD %#x\n", prop_dword.dwData );
8837 set_hid_expect( file, NULL, 0 );
8839 set_hid_expect( file, expect_pool, sizeof(struct hid_expect) );
8840 res = 0xdeadbeef;
8841 hr = IDirectInputDevice8_GetForceFeedbackState( device, &res );
8842 todo_wine
8843 ok( hr == DI_OK, "GetForceFeedbackState returned %#x\n", hr );
8844 flags = DIGFFS_STOPPED|DIGFFS_EMPTY;
8845 todo_wine
8846 ok( res == flags, "got state %#x\n", res );
8847 set_hid_expect( file, NULL, 0 );
8849 set_hid_expect( file, expect_pool, sizeof(struct hid_expect) );
8850 prop_dword.dwData = 0xdeadbeef;
8851 hr = IDirectInputDevice8_GetProperty( device, DIPROP_FFLOAD, &prop_dword.diph );
8852 ok( hr == DI_OK, "GetProperty DIPROP_FFLOAD returned %#x\n", hr );
8853 ok( prop_dword.dwData == 0, "got DIPROP_FFLOAD %#x\n", prop_dword.dwData );
8854 set_hid_expect( file, NULL, 0 );
8856 send_hid_input( file, device_state_input, sizeof(struct hid_expect) );
8857 res = WaitForSingleObject( event, 100 );
8858 ok( res == WAIT_TIMEOUT, "WaitForSingleObject returned %#x\n", res );
8859 send_hid_input( file, device_state_input, sizeof(device_state_input) );
8860 res = WaitForSingleObject( event, 100 );
8861 ok( res == WAIT_OBJECT_0, "WaitForSingleObject returned %#x\n", res );
8863 set_hid_expect( file, expect_pool, sizeof(struct hid_expect) );
8864 res = 0xdeadbeef;
8865 hr = IDirectInputDevice8_GetForceFeedbackState( device, &res );
8866 todo_wine
8867 ok( hr == DI_OK, "GetForceFeedbackState returned %#x\n", hr );
8868 flags = DIGFFS_PAUSED|DIGFFS_EMPTY|DIGFFS_ACTUATORSON|DIGFFS_POWERON|DIGFFS_SAFETYSWITCHON|DIGFFS_USERFFSWITCHON;
8869 todo_wine
8870 ok( res == flags, "got state %#x\n", res );
8871 set_hid_expect( file, NULL, 0 );
8873 hr = IDirectInputDevice8_CreateEffect( device, &GUID_Spring, NULL, &effect, NULL );
8874 ok( hr == DI_OK, "CreateEffect returned %#x\n", hr );
8876 hr = IDirectInputEffect_GetEffectStatus( effect, NULL );
8877 ok( hr == E_POINTER, "GetEffectStatus returned %#x\n", hr );
8878 res = 0xdeadbeef;
8879 hr = IDirectInputEffect_GetEffectStatus( effect, &res );
8880 todo_wine
8881 ok( hr == DIERR_NOTDOWNLOADED, "GetEffectStatus returned %#x\n", hr );
8882 todo_wine
8883 ok( res == 0, "got status %#x\n", res );
8885 flags = DIEP_ALLPARAMS;
8886 hr = IDirectInputEffect_SetParameters( effect, &expect_desc, flags | DIEP_NODOWNLOAD );
8887 ok( hr == DI_DOWNLOADSKIPPED, "SetParameters returned %#x\n", hr );
8889 set_hid_expect( file, expect_reset, sizeof(struct hid_expect) );
8890 hr = IDirectInputDevice8_Unacquire( device );
8891 ok( hr == DI_OK, "Unacquire returned: %#x\n", hr );
8892 set_hid_expect( file, NULL, 0 );
8894 hr = IDirectInputEffect_GetEffectStatus( effect, &res );
8895 todo_wine
8896 ok( hr == DIERR_NOTEXCLUSIVEACQUIRED, "GetEffectStatus returned %#x\n", hr );
8898 set_hid_expect( file, expect_reset, sizeof(expect_reset) );
8899 hr = IDirectInputDevice8_Acquire( device );
8900 ok( hr == DI_OK, "Acquire returned: %#x\n", hr );
8901 wait_hid_expect( file, 100 );
8903 res = 0xdeadbeef;
8904 hr = IDirectInputEffect_GetEffectStatus( effect, &res );
8905 todo_wine
8906 ok( hr == DIERR_NOTDOWNLOADED, "GetEffectStatus returned %#x\n", hr );
8907 todo_wine
8908 ok( res == 0, "got status %#x\n", res );
8910 set_hid_expect( file, expect_pool, sizeof(struct hid_expect) );
8911 res = 0xdeadbeef;
8912 hr = IDirectInputDevice8_GetForceFeedbackState( device, &res );
8913 todo_wine
8914 ok( hr == DI_OK, "GetForceFeedbackState returned %#x\n", hr );
8915 flags = DIGFFS_STOPPED|DIGFFS_EMPTY;
8916 todo_wine
8917 ok( res == flags, "got state %#x\n", res );
8918 set_hid_expect( file, NULL, 0 );
8920 set_hid_expect( file, expect_create, sizeof(expect_create) );
8921 hr = IDirectInputEffect_Download( effect );
8922 ok( hr == DI_OK, "Download returned %#x\n", hr );
8923 set_hid_expect( file, NULL, 0 );
8925 res = 0xdeadbeef;
8926 hr = IDirectInputEffect_GetEffectStatus( effect, &res );
8927 todo_wine
8928 ok( hr == DI_OK, "GetEffectStatus returned %#x\n", hr );
8929 todo_wine
8930 ok( res == 0, "got status %#x\n", res );
8931 set_hid_expect( file, expect_pool, sizeof(struct hid_expect) );
8932 res = 0xdeadbeef;
8933 hr = IDirectInputDevice8_GetForceFeedbackState( device, &res );
8934 todo_wine
8935 ok( hr == DI_OK, "GetForceFeedbackState returned %#x\n", hr );
8936 flags = DIGFFS_STOPPED;
8937 todo_wine
8938 ok( res == flags, "got state %#x\n", res );
8939 set_hid_expect( file, NULL, 0 );
8941 set_hid_expect( file, expect_pool, sizeof(struct hid_expect) );
8942 prop_dword.dwData = 0xdeadbeef;
8943 hr = IDirectInputDevice8_GetProperty( device, DIPROP_FFLOAD, &prop_dword.diph );
8944 ok( hr == DI_OK, "GetProperty DIPROP_FFLOAD returned %#x\n", hr );
8945 ok( prop_dword.dwData == 0, "got DIPROP_FFLOAD %#x\n", prop_dword.dwData );
8946 set_hid_expect( file, NULL, 0 );
8948 set_hid_expect( file, &expect_start, sizeof(expect_start) );
8949 hr = IDirectInputEffect_Start( effect, 1, DIES_NODOWNLOAD );
8950 ok( hr == DI_OK, "Start returned %#x\n", hr );
8951 set_hid_expect( file, NULL, 0 );
8953 res = 0xdeadbeef;
8954 hr = IDirectInputEffect_GetEffectStatus( effect, &res );
8955 todo_wine
8956 ok( hr == DI_OK, "GetEffectStatus returned %#x\n", hr );
8957 todo_wine
8958 ok( res == DIEGES_PLAYING, "got status %#x\n", res );
8960 send_hid_input( file, device_state_input_1, sizeof(device_state_input_1) );
8961 res = WaitForSingleObject( event, 100 );
8962 ok( res == WAIT_OBJECT_0, "WaitForSingleObject returned %#x\n", res );
8963 res = 0xdeadbeef;
8964 hr = IDirectInputEffect_GetEffectStatus( effect, &res );
8965 todo_wine
8966 ok( hr == DI_OK, "GetEffectStatus returned %#x\n", hr );
8967 todo_wine
8968 ok( res == DIEGES_PLAYING, "got status %#x\n", res );
8969 set_hid_expect( file, expect_pool, sizeof(struct hid_expect) );
8970 res = 0xdeadbeef;
8971 hr = IDirectInputDevice8_GetForceFeedbackState( device, &res );
8972 todo_wine
8973 ok( hr == DI_OK, "GetForceFeedbackState returned %#x\n", hr );
8974 flags = DIGFFS_ACTUATORSOFF|DIGFFS_POWEROFF|DIGFFS_SAFETYSWITCHOFF|DIGFFS_USERFFSWITCHOFF;
8975 todo_wine
8976 ok( res == flags, "got state %#x\n", res );
8977 set_hid_expect( file, NULL, 0 );
8979 send_hid_input( file, device_state_input_2, sizeof(device_state_input_2) );
8980 res = WaitForSingleObject( event, 100 );
8981 ok( res == WAIT_OBJECT_0, "WaitForSingleObject returned %#x\n", res );
8982 res = 0xdeadbeef;
8983 hr = IDirectInputEffect_GetEffectStatus( effect, &res );
8984 todo_wine
8985 ok( hr == DI_OK, "GetEffectStatus returned %#x\n", hr );
8986 todo_wine
8987 ok( res == DIEGES_PLAYING, "got status %#x\n", res );
8988 set_hid_expect( file, expect_pool, sizeof(struct hid_expect) );
8989 res = 0xdeadbeef;
8990 hr = IDirectInputDevice8_GetForceFeedbackState( device, &res );
8991 todo_wine
8992 ok( hr == DI_OK, "GetForceFeedbackState returned %#x\n", hr );
8993 flags = DIGFFS_PAUSED|DIGFFS_ACTUATORSON|DIGFFS_POWEROFF|DIGFFS_SAFETYSWITCHOFF|DIGFFS_USERFFSWITCHOFF;
8994 todo_wine
8995 ok( res == flags, "got state %#x\n", res );
8996 set_hid_expect( file, NULL, 0 );
8998 set_hid_expect( file, &expect_stop, sizeof(expect_stop) );
8999 hr = IDirectInputEffect_Stop( effect );
9000 ok( hr == DI_OK, "Stop returned %#x\n", hr );
9001 set_hid_expect( file, NULL, 0 );
9003 res = 0xdeadbeef;
9004 hr = IDirectInputEffect_GetEffectStatus( effect, &res );
9005 todo_wine
9006 ok( hr == DI_OK, "GetEffectStatus returned %#x\n", hr );
9007 todo_wine
9008 ok( res == 0, "got status %#x\n", res );
9009 set_hid_expect( file, expect_pool, sizeof(struct hid_expect) );
9010 res = 0xdeadbeef;
9011 hr = IDirectInputDevice8_GetForceFeedbackState( device, &res );
9012 todo_wine
9013 ok( hr == DI_OK, "GetForceFeedbackState returned %#x\n", hr );
9014 flags = DIGFFS_PAUSED|DIGFFS_ACTUATORSON|DIGFFS_POWEROFF|DIGFFS_SAFETYSWITCHOFF|DIGFFS_USERFFSWITCHOFF;
9015 todo_wine
9016 ok( res == flags, "got state %#x\n", res );
9017 set_hid_expect( file, NULL, 0 );
9019 set_hid_expect( file, expect_destroy, sizeof(expect_destroy) );
9020 hr = IDirectInputEffect_Unload( effect );
9021 ok( hr == DI_OK, "Unload returned %#x\n", hr );
9022 set_hid_expect( file, NULL, 0 );
9024 res = 0xdeadbeef;
9025 hr = IDirectInputEffect_GetEffectStatus( effect, &res );
9026 todo_wine
9027 ok( hr == DIERR_NOTDOWNLOADED, "GetEffectStatus returned %#x\n", hr );
9028 todo_wine
9029 ok( res == 0, "got status %#x\n", res );
9030 set_hid_expect( file, expect_pool, sizeof(struct hid_expect) );
9031 res = 0xdeadbeef;
9032 hr = IDirectInputDevice8_GetForceFeedbackState( device, &res );
9033 todo_wine
9034 ok( hr == DI_OK, "GetForceFeedbackState returned %#x\n", hr );
9035 flags = DIGFFS_EMPTY|DIGFFS_PAUSED|DIGFFS_ACTUATORSON|DIGFFS_POWEROFF|DIGFFS_SAFETYSWITCHOFF|DIGFFS_USERFFSWITCHOFF;
9036 todo_wine
9037 ok( res == flags, "got state %#x\n", res );
9038 set_hid_expect( file, NULL, 0 );
9040 ref = IDirectInputEffect_Release( effect );
9041 ok( ref == 0, "Release returned %d\n", ref );
9043 set_hid_expect( file, expect_reset, sizeof(struct hid_expect) );
9044 hr = IDirectInputDevice8_Unacquire( device );
9045 ok( hr == DI_OK, "Unacquire returned: %#x\n", hr );
9046 set_hid_expect( file, NULL, 0 );
9048 ref = IDirectInputDevice8_Release( device );
9049 ok( ref == 0, "Release returned %d\n", ref );
9051 DestroyWindow( hwnd );
9052 CloseHandle( event );
9053 CloseHandle( file );
9055 done:
9056 pnp_driver_stop();
9057 cleanup_registry_keys();
9058 SetCurrentDirectoryW( cwd );
9059 winetest_pop_context();
9062 START_TEST( hid )
9064 HANDLE mapping;
9065 BOOL is_wow64;
9067 instance = GetModuleHandleW( NULL );
9068 localized = GetUserDefaultLCID() != MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
9069 pSignerSign = (void *)GetProcAddress( LoadLibraryW( L"mssign32" ), "SignerSign" );
9071 if (IsWow64Process( GetCurrentProcess(), &is_wow64 ) && is_wow64)
9073 skip( "Running in WoW64.\n" );
9074 return;
9077 mapping = CreateFileMappingW( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(*test_data),
9078 L"Global\\winetest_dinput_section" );
9079 if (!mapping && GetLastError() == ERROR_ACCESS_DENIED)
9081 win_skip( "Failed to create test data mapping.\n" );
9082 return;
9084 ok( !!mapping, "got error %u\n", GetLastError() );
9085 test_data = MapViewOfFile( mapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 1024 );
9086 test_data->running_under_wine = !strcmp( winetest_platform, "wine" );
9087 test_data->winetest_report_success = winetest_report_success;
9088 test_data->winetest_debug = winetest_debug;
9090 okfile = CreateFileW( L"C:\\windows\\winetest_dinput_okfile", GENERIC_READ | GENERIC_WRITE,
9091 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL );
9092 ok( okfile != INVALID_HANDLE_VALUE, "failed to create file, error %u\n", GetLastError() );
9094 subtest( "driver_hid" );
9095 test_hidp_kdr();
9096 test_hid_driver( 0, FALSE );
9097 test_hid_driver( 1, FALSE );
9098 test_hid_driver( 0, TRUE );
9099 test_hid_driver( 1, TRUE );
9101 CoInitialize( NULL );
9102 if (test_device_types( 0x800 ))
9104 test_device_types( 0x500 );
9105 test_device_types( 0x700 );
9107 test_simple_joystick();
9108 test_force_feedback_joystick( 0x500 );
9109 test_force_feedback_joystick( 0x700 );
9110 test_force_feedback_joystick( 0x800 );
9112 test_device_managed_effect();
9114 CoUninitialize();
9116 UnmapViewOfFile( test_data );
9117 CloseHandle( mapping );
9118 CloseHandle( okfile );
9119 DeleteFileW( L"C:\\windows\\winetest_dinput_okfile" );