dinput8/tests: Add some HID joystick IDirectInputDevice8_EnumObjects tests.
[wine.git] / dlls / dinput8 / tests / hid.c
blob4316f2f8bb8560563281ada3de10825b9a2426c0
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"
49 #include "initguid.h"
50 #include "ddk/wdm.h"
51 #include "ddk/hidclass.h"
52 #include "ddk/hidsdi.h"
53 #include "ddk/hidpi.h"
54 #include "ddk/hidport.h"
55 #include "hidusage.h"
56 #include "devguid.h"
58 #include "wine/test.h"
59 #include "wine/mssign.h"
61 #include "driver_hid.h"
63 static HINSTANCE instance;
64 static BOOL localized; /* object names get translated */
66 #define EXPECT_VIDPID MAKELONG( 0x1209, 0x0001 )
67 static const WCHAR expect_vidpid_str[] = L"VID_1209&PID_0001";
68 static const GUID expect_guid_product = {EXPECT_VIDPID,0x0000,0x0000,{0x00,0x00,'P','I','D','V','I','D'}};
69 static const WCHAR expect_path[] = L"\\\\?\\hid#winetest#1&2fafeb0&";
70 static const WCHAR expect_path_end[] = L"&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}";
72 static struct winetest_shared_data *test_data;
73 static HANDLE okfile;
75 static HRESULT (WINAPI *pSignerSign)( SIGNER_SUBJECT_INFO *subject, SIGNER_CERT *cert,
76 SIGNER_SIGNATURE_INFO *signature, SIGNER_PROVIDER_INFO *provider,
77 const WCHAR *timestamp, CRYPT_ATTRIBUTES *attr, void *sip_data );
79 static const WCHAR container_name[] = L"wine_testsign";
81 static const CERT_CONTEXT *testsign_sign( const WCHAR *filename )
83 BYTE encoded_name[100], encoded_key_id[200], public_key_info_buffer[1000];
84 BYTE hash_buffer[16], cert_buffer[1000], provider_nameA[100], serial[16];
85 CERT_PUBLIC_KEY_INFO *public_key_info = (CERT_PUBLIC_KEY_INFO *)public_key_info_buffer;
86 SIGNER_SIGNATURE_INFO signature = {sizeof(SIGNER_SIGNATURE_INFO)};
87 SIGNER_CERT_STORE_INFO store = {sizeof(SIGNER_CERT_STORE_INFO)};
88 SIGNER_ATTR_AUTHCODE authcode = {sizeof(SIGNER_ATTR_AUTHCODE)};
89 SIGNER_SUBJECT_INFO subject = {sizeof(SIGNER_SUBJECT_INFO)};
90 SIGNER_FILE_INFO file = {sizeof(SIGNER_FILE_INFO)};
91 SIGNER_CERT signer = {sizeof(SIGNER_CERT)};
92 CRYPT_KEY_PROV_INFO provider_info = {0};
93 CRYPT_ALGORITHM_IDENTIFIER algid = {0};
94 CERT_AUTHORITY_KEY_ID_INFO key_info;
95 HCERTSTORE root_store, pub_store;
96 CERT_INFO cert_info = {0};
97 WCHAR provider_nameW[100];
98 const CERT_CONTEXT *cert;
99 CERT_EXTENSION extension;
100 DWORD size, index = 0;
101 HCRYPTPROV provider;
102 HCRYPTKEY key;
103 HRESULT hr;
104 BOOL ret;
106 ret = CryptAcquireContextW( &provider, container_name, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET );
107 if (!ret && GetLastError() == NTE_EXISTS)
109 ret = CryptAcquireContextW( &provider, container_name, NULL, PROV_RSA_FULL, CRYPT_DELETEKEYSET );
110 ok( ret, "Failed to delete container, error %#x\n", GetLastError() );
111 ret = CryptAcquireContextW( &provider, container_name, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET );
113 ok( ret, "Failed to create container, error %#x\n", GetLastError() );
115 ret = CryptGenKey( provider, AT_SIGNATURE, CRYPT_EXPORTABLE, &key );
116 ok( ret, "Failed to create key, error %#x\n", GetLastError() );
117 ret = CryptDestroyKey( key );
118 ok( ret, "Failed to destroy key, error %#x\n", GetLastError() );
119 ret = CryptGetUserKey( provider, AT_SIGNATURE, &key );
120 ok( ret, "Failed to get user key, error %#x\n", GetLastError() );
121 ret = CryptDestroyKey( key );
122 ok( ret, "Failed to destroy key, error %#x\n", GetLastError() );
124 size = sizeof(encoded_name);
125 ret = CertStrToNameW( X509_ASN_ENCODING, L"CN=winetest_cert", CERT_X500_NAME_STR, NULL,
126 encoded_name, &size, NULL );
127 ok( ret, "Failed to convert name, error %#x\n", GetLastError() );
128 key_info.CertIssuer.cbData = size;
129 key_info.CertIssuer.pbData = encoded_name;
131 size = sizeof(public_key_info_buffer);
132 ret = CryptExportPublicKeyInfo( provider, AT_SIGNATURE, X509_ASN_ENCODING, public_key_info, &size );
133 ok( ret, "Failed to export public key, error %#x\n", GetLastError() );
134 cert_info.SubjectPublicKeyInfo = *public_key_info;
136 size = sizeof(hash_buffer);
137 ret = CryptHashPublicKeyInfo( provider, CALG_MD5, 0, X509_ASN_ENCODING, public_key_info, hash_buffer, &size );
138 ok( ret, "Failed to hash public key, error %#x\n", GetLastError() );
140 key_info.KeyId.cbData = size;
141 key_info.KeyId.pbData = hash_buffer;
143 RtlGenRandom( serial, sizeof(serial) );
144 key_info.CertSerialNumber.cbData = sizeof(serial);
145 key_info.CertSerialNumber.pbData = serial;
147 size = sizeof(encoded_key_id);
148 ret = CryptEncodeObject( X509_ASN_ENCODING, X509_AUTHORITY_KEY_ID, &key_info, encoded_key_id, &size );
149 ok( ret, "Failed to convert name, error %#x\n", GetLastError() );
151 extension.pszObjId = (char *)szOID_AUTHORITY_KEY_IDENTIFIER;
152 extension.fCritical = TRUE;
153 extension.Value.cbData = size;
154 extension.Value.pbData = encoded_key_id;
156 cert_info.dwVersion = CERT_V3;
157 cert_info.SerialNumber = key_info.CertSerialNumber;
158 cert_info.SignatureAlgorithm.pszObjId = (char *)szOID_RSA_SHA1RSA;
159 cert_info.Issuer = key_info.CertIssuer;
160 GetSystemTimeAsFileTime( &cert_info.NotBefore );
161 GetSystemTimeAsFileTime( &cert_info.NotAfter );
162 cert_info.NotAfter.dwHighDateTime += 1;
163 cert_info.Subject = key_info.CertIssuer;
164 cert_info.cExtension = 1;
165 cert_info.rgExtension = &extension;
166 algid.pszObjId = (char *)szOID_RSA_SHA1RSA;
167 size = sizeof(cert_buffer);
168 ret = CryptSignAndEncodeCertificate( provider, AT_SIGNATURE, X509_ASN_ENCODING, X509_CERT_TO_BE_SIGNED,
169 &cert_info, &algid, NULL, cert_buffer, &size );
170 ok( ret, "Failed to create certificate, error %#x\n", GetLastError() );
172 cert = CertCreateCertificateContext( X509_ASN_ENCODING, cert_buffer, size );
173 ok( !!cert, "Failed to create context, error %#x\n", GetLastError() );
175 size = sizeof(provider_nameA);
176 ret = CryptGetProvParam( provider, PP_NAME, provider_nameA, &size, 0 );
177 ok( ret, "Failed to get prov param, error %#x\n", GetLastError() );
178 MultiByteToWideChar( CP_ACP, 0, (char *)provider_nameA, -1, provider_nameW, ARRAY_SIZE(provider_nameW) );
180 provider_info.pwszContainerName = (WCHAR *)container_name;
181 provider_info.pwszProvName = provider_nameW;
182 provider_info.dwProvType = PROV_RSA_FULL;
183 provider_info.dwKeySpec = AT_SIGNATURE;
184 ret = CertSetCertificateContextProperty( cert, CERT_KEY_PROV_INFO_PROP_ID, 0, &provider_info );
185 ok( ret, "Failed to set provider info, error %#x\n", GetLastError() );
187 ret = CryptReleaseContext( provider, 0 );
188 ok( ret, "failed to release context, error %u\n", GetLastError() );
190 root_store = CertOpenStore( CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE, L"root" );
191 if (!root_store && GetLastError() == ERROR_ACCESS_DENIED)
193 win_skip( "Failed to open root store.\n" );
194 ret = CertFreeCertificateContext( cert );
195 ok( ret, "Failed to free certificate, error %u\n", GetLastError() );
196 return NULL;
198 ok( !!root_store, "Failed to open store, error %u\n", GetLastError() );
199 ret = CertAddCertificateContextToStore( root_store, cert, CERT_STORE_ADD_ALWAYS, NULL );
200 if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
202 win_skip( "Failed to add self-signed certificate to store.\n" );
203 ret = CertFreeCertificateContext( cert );
204 ok( ret, "Failed to free certificate, error %u\n", GetLastError() );
205 ret = CertCloseStore( root_store, CERT_CLOSE_STORE_CHECK_FLAG );
206 ok( ret, "Failed to close store, error %u\n", GetLastError() );
207 return NULL;
209 ok( ret, "Failed to add certificate, error %u\n", GetLastError() );
210 ret = CertCloseStore( root_store, CERT_CLOSE_STORE_CHECK_FLAG );
211 ok( ret, "Failed to close store, error %u\n", GetLastError() );
213 pub_store = CertOpenStore( CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0,
214 CERT_SYSTEM_STORE_LOCAL_MACHINE, L"trustedpublisher" );
215 ok( !!pub_store, "Failed to open store, error %u\n", GetLastError() );
216 ret = CertAddCertificateContextToStore( pub_store, cert, CERT_STORE_ADD_ALWAYS, NULL );
217 ok( ret, "Failed to add certificate, error %u\n", GetLastError() );
218 ret = CertCloseStore( pub_store, CERT_CLOSE_STORE_CHECK_FLAG );
219 ok( ret, "Failed to close store, error %u\n", GetLastError() );
221 subject.dwSubjectChoice = 1;
222 subject.pdwIndex = &index;
223 subject.pSignerFileInfo = &file;
224 file.pwszFileName = (WCHAR *)filename;
225 signer.dwCertChoice = 2;
226 signer.pCertStoreInfo = &store;
227 store.pSigningCert = cert;
228 store.dwCertPolicy = 0;
229 signature.algidHash = CALG_SHA_256;
230 signature.dwAttrChoice = SIGNER_AUTHCODE_ATTR;
231 signature.pAttrAuthcode = &authcode;
232 authcode.pwszName = L"";
233 authcode.pwszInfo = L"";
234 hr = pSignerSign( &subject, &signer, &signature, NULL, NULL, NULL, NULL );
235 todo_wine
236 ok( hr == S_OK || broken( hr == NTE_BAD_ALGID ) /* < 7 */, "Failed to sign, hr %#x\n", hr );
238 return cert;
241 static void testsign_cleanup( const CERT_CONTEXT *cert )
243 HCERTSTORE root_store, pub_store;
244 const CERT_CONTEXT *store_cert;
245 HCRYPTPROV provider;
246 BOOL ret;
248 root_store = CertOpenStore( CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE, L"root" );
249 ok( !!root_store, "Failed to open store, error %u\n", GetLastError() );
250 store_cert = CertFindCertificateInStore( root_store, X509_ASN_ENCODING, 0, CERT_FIND_EXISTING, cert, NULL );
251 ok( !!store_cert, "Failed to find root certificate, error %u\n", GetLastError() );
252 ret = CertDeleteCertificateFromStore( store_cert );
253 ok( ret, "Failed to remove certificate, error %u\n", GetLastError() );
254 ret = CertCloseStore( root_store, CERT_CLOSE_STORE_CHECK_FLAG );
255 ok( ret, "Failed to close store, error %u\n", GetLastError() );
257 pub_store = CertOpenStore( CERT_STORE_PROV_SYSTEM_REGISTRY_W, 0, 0,
258 CERT_SYSTEM_STORE_LOCAL_MACHINE, L"trustedpublisher" );
259 ok( !!pub_store, "Failed to open store, error %u\n", GetLastError() );
260 store_cert = CertFindCertificateInStore( pub_store, X509_ASN_ENCODING, 0, CERT_FIND_EXISTING, cert, NULL );
261 ok( !!store_cert, "Failed to find publisher certificate, error %u\n", GetLastError() );
262 ret = CertDeleteCertificateFromStore( store_cert );
263 ok( ret, "Failed to remove certificate, error %u\n", GetLastError() );
264 ret = CertCloseStore( pub_store, CERT_CLOSE_STORE_CHECK_FLAG );
265 ok( ret, "Failed to close store, error %u\n", GetLastError() );
267 ret = CertFreeCertificateContext( cert );
268 ok( ret, "Failed to free certificate, error %u\n", GetLastError() );
270 ret = CryptAcquireContextW( &provider, container_name, NULL, PROV_RSA_FULL, CRYPT_DELETEKEYSET );
271 ok( ret, "Failed to delete container, error %#x\n", GetLastError() );
274 static void load_resource( const WCHAR *name, WCHAR *filename )
276 static WCHAR path[MAX_PATH];
277 DWORD written;
278 HANDLE file;
279 HRSRC res;
280 void *ptr;
282 GetTempPathW( ARRAY_SIZE(path), path );
283 GetTempFileNameW( path, name, 0, filename );
285 file = CreateFileW( filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 );
286 ok( file != INVALID_HANDLE_VALUE, "failed to create %s, error %u\n", debugstr_w(filename), GetLastError() );
288 res = FindResourceW( NULL, name, L"TESTDLL" );
289 ok( res != 0, "couldn't find resource\n" );
290 ptr = LockResource( LoadResource( GetModuleHandleW( NULL ), res ) );
291 WriteFile( file, ptr, SizeofResource( GetModuleHandleW( NULL ), res ), &written, NULL );
292 ok( written == SizeofResource( GetModuleHandleW( NULL ), res ), "couldn't write resource\n" );
293 CloseHandle( file );
296 #ifdef __i386__
297 #define EXT "x86"
298 #elif defined(__x86_64__)
299 #define EXT "amd64"
300 #elif defined(__arm__)
301 #define EXT "arm"
302 #elif defined(__aarch64__)
303 #define EXT "arm64"
304 #else
305 #define EXT
306 #endif
308 static const char inf_text[] =
309 "[Version]\n"
310 "Signature=$Chicago$\n"
311 "ClassGuid={4d36e97d-e325-11ce-bfc1-08002be10318}\n"
312 "CatalogFile=winetest.cat\n"
313 "DriverVer=09/21/2006,6.0.5736.1\n"
315 "[Manufacturer]\n"
316 "Wine=mfg_section,NT" EXT "\n"
318 "[mfg_section.NT" EXT "]\n"
319 "Wine test root driver=device_section,test_hardware_id\n"
321 "[device_section.NT" EXT "]\n"
322 "CopyFiles=file_section\n"
324 "[device_section.NT" EXT ".Services]\n"
325 "AddService=winetest,0x2,svc_section\n"
327 "[file_section]\n"
328 "winetest.sys\n"
330 "[SourceDisksFiles]\n"
331 "winetest.sys=1\n"
333 "[SourceDisksNames]\n"
334 "1=,winetest.sys\n"
336 "[DestinationDirs]\n"
337 "DefaultDestDir=12\n"
339 "[svc_section]\n"
340 "ServiceBinary=%12%\\winetest.sys\n"
341 "ServiceType=1\n"
342 "StartType=3\n"
343 "ErrorControl=1\n"
344 "LoadOrderGroup=Extended Base\n"
345 "DisplayName=\"winetest bus driver\"\n"
346 "; they don't sleep anymore, on the beach\n";
348 static void add_file_to_catalog( HANDLE catalog, const WCHAR *file )
350 SIP_SUBJECTINFO subject_info = {sizeof(SIP_SUBJECTINFO)};
351 SIP_INDIRECT_DATA *indirect_data;
352 const WCHAR *filepart = file;
353 CRYPTCATMEMBER *member;
354 WCHAR hash_buffer[100];
355 GUID subject_guid;
356 unsigned int i;
357 DWORD size;
358 BOOL ret;
360 ret = CryptSIPRetrieveSubjectGuidForCatalogFile( file, NULL, &subject_guid );
361 todo_wine
362 ok( ret, "Failed to get subject guid, error %u\n", GetLastError() );
364 size = 0;
365 subject_info.pgSubjectType = &subject_guid;
366 subject_info.pwsFileName = file;
367 subject_info.DigestAlgorithm.pszObjId = (char *)szOID_OIWSEC_sha1;
368 subject_info.dwFlags = SPC_INC_PE_RESOURCES_FLAG | SPC_INC_PE_IMPORT_ADDR_TABLE_FLAG |
369 SPC_EXC_PE_PAGE_HASHES_FLAG | 0x10000;
370 ret = CryptSIPCreateIndirectData( &subject_info, &size, NULL );
371 todo_wine
372 ok( ret, "Failed to get indirect data size, error %u\n", GetLastError() );
374 indirect_data = malloc( size );
375 ret = CryptSIPCreateIndirectData( &subject_info, &size, indirect_data );
376 todo_wine
377 ok( ret, "Failed to get indirect data, error %u\n", GetLastError() );
378 if (ret)
380 memset( hash_buffer, 0, sizeof(hash_buffer) );
381 for (i = 0; i < indirect_data->Digest.cbData; ++i)
382 swprintf( &hash_buffer[i * 2], 2, L"%02X", indirect_data->Digest.pbData[i] );
384 member = CryptCATPutMemberInfo( catalog, (WCHAR *)file, hash_buffer, &subject_guid,
385 0, size, (BYTE *)indirect_data );
386 ok( !!member, "Failed to write member, error %u\n", GetLastError() );
388 if (wcsrchr( file, '\\' )) filepart = wcsrchr( file, '\\' ) + 1;
390 ret = !!CryptCATPutAttrInfo( catalog, member, (WCHAR *)L"File",
391 CRYPTCAT_ATTR_NAMEASCII | CRYPTCAT_ATTR_DATAASCII | CRYPTCAT_ATTR_AUTHENTICATED,
392 (wcslen( filepart ) + 1) * 2, (BYTE *)filepart );
393 ok( ret, "Failed to write attr, error %u\n", GetLastError() );
395 ret = !!CryptCATPutAttrInfo( catalog, member, (WCHAR *)L"OSAttr",
396 CRYPTCAT_ATTR_NAMEASCII | CRYPTCAT_ATTR_DATAASCII | CRYPTCAT_ATTR_AUTHENTICATED,
397 sizeof(L"2:6.0"), (BYTE *)L"2:6.0" );
398 ok( ret, "Failed to write attr, error %u\n", GetLastError() );
402 static void unload_driver( SC_HANDLE service )
404 SERVICE_STATUS status;
406 ControlService( service, SERVICE_CONTROL_STOP, &status );
407 while (status.dwCurrentState == SERVICE_STOP_PENDING)
409 BOOL ret;
410 Sleep( 100 );
411 ret = QueryServiceStatus( service, &status );
412 ok( ret, "QueryServiceStatus failed: %u\n", GetLastError() );
414 ok( status.dwCurrentState == SERVICE_STOPPED, "expected SERVICE_STOPPED, got %d\n", status.dwCurrentState );
416 DeleteService( service );
417 CloseServiceHandle( service );
420 static void pnp_driver_stop(void)
422 SP_DEVINFO_DATA device = {sizeof(SP_DEVINFO_DATA)};
423 WCHAR path[MAX_PATH], dest[MAX_PATH], *filepart;
424 SC_HANDLE manager, service;
425 char buffer[512];
426 HDEVINFO set;
427 HANDLE file;
428 DWORD size;
429 BOOL ret;
431 set = SetupDiCreateDeviceInfoList( NULL, NULL );
432 ok( set != INVALID_HANDLE_VALUE, "failed to create device list, error %u\n", GetLastError() );
434 ret = SetupDiOpenDeviceInfoW( set, L"root\\winetest\\0", NULL, 0, &device );
435 if (!ret && GetLastError() == ERROR_NO_SUCH_DEVINST)
437 ret = SetupDiDestroyDeviceInfoList( set );
438 ok( ret, "failed to destroy set, error %u\n", GetLastError() );
439 return;
441 ok( ret, "failed to open device, error %u\n", GetLastError() );
443 ret = SetupDiCallClassInstaller( DIF_REMOVE, set, &device );
444 ok( ret, "failed to remove device, error %u\n", GetLastError() );
446 file = CreateFileW( L"\\\\?\\root#winetest#0#{deadbeef-29ef-4538-a5fd-b69573a362c0}", 0, 0,
447 NULL, OPEN_EXISTING, 0, NULL );
448 ok( file == INVALID_HANDLE_VALUE, "expected failure\n" );
449 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "got error %u\n", GetLastError() );
451 ret = SetupDiDestroyDeviceInfoList( set );
452 ok( ret, "failed to destroy set, error %u\n", GetLastError() );
454 /* Windows stops the service but does not delete it. */
455 manager = OpenSCManagerW( NULL, NULL, SC_MANAGER_CONNECT );
456 ok( !!manager, "failed to open service manager, error %u\n", GetLastError() );
458 service = OpenServiceW( manager, L"winetest", SERVICE_STOP | DELETE );
459 if (service) unload_driver( service );
460 else ok( GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST, "got error %u\n", GetLastError() );
462 CloseServiceHandle( manager );
464 SetFilePointer( okfile, 0, NULL, FILE_BEGIN );
467 ReadFile( okfile, buffer, sizeof(buffer), &size, NULL );
468 printf( "%.*s", size, buffer );
469 } while (size == sizeof(buffer));
470 SetFilePointer( okfile, 0, NULL, FILE_BEGIN );
471 SetEndOfFile( okfile );
473 winetest_add_failures( InterlockedExchange( &test_data->failures, 0 ) );
474 winetest_add_failures( InterlockedExchange( &test_data->todo_failures, 0 ) );
476 GetFullPathNameW( L"winetest.inf", ARRAY_SIZE(path), path, NULL );
477 ret = SetupCopyOEMInfW( path, NULL, 0, 0, dest, ARRAY_SIZE(dest), NULL, &filepart );
478 ok( ret, "Failed to copy INF, error %u\n", GetLastError() );
479 ret = SetupUninstallOEMInfW( filepart, 0, NULL );
480 ok( ret, "Failed to uninstall INF, error %u\n", GetLastError() );
482 ret = DeleteFileW( L"winetest.cat" );
483 ok( ret, "Failed to delete file, error %u\n", GetLastError() );
484 ret = DeleteFileW( L"winetest.inf" );
485 ok( ret, "Failed to delete file, error %u\n", GetLastError() );
486 ret = DeleteFileW( L"winetest.sys" );
487 ok( ret, "Failed to delete file, error %u\n", GetLastError() );
488 /* Windows 10 apparently deletes the image in SetupUninstallOEMInf(). */
489 ret = DeleteFileW( L"C:/windows/system32/drivers/winetest.sys" );
490 ok( ret || GetLastError() == ERROR_FILE_NOT_FOUND, "Failed to delete file, error %u\n", GetLastError() );
493 static BOOL pnp_driver_start( const WCHAR *resource )
495 static const WCHAR hardware_id[] = L"test_hardware_id\0";
496 SP_DEVINFO_DATA device = {sizeof(SP_DEVINFO_DATA)};
497 WCHAR path[MAX_PATH], filename[MAX_PATH];
498 SC_HANDLE manager, service;
499 const CERT_CONTEXT *cert;
500 BOOL ret, need_reboot;
501 HANDLE catalog;
502 HDEVINFO set;
503 FILE *f;
505 load_resource( resource, filename );
506 ret = MoveFileExW( filename, L"winetest.sys", MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING );
507 ok( ret, "failed to move file, error %u\n", GetLastError() );
509 f = fopen( "winetest.inf", "w" );
510 ok( !!f, "failed to open winetest.inf: %s\n", strerror( errno ) );
511 fputs( inf_text, f );
512 fclose( f );
514 /* Create the catalog file. */
516 catalog = CryptCATOpen( (WCHAR *)L"winetest.cat", CRYPTCAT_OPEN_CREATENEW, 0, CRYPTCAT_VERSION_1, 0 );
517 ok( catalog != INVALID_HANDLE_VALUE, "Failed to create catalog, error %u\n", GetLastError() );
519 add_file_to_catalog( catalog, L"winetest.sys" );
520 add_file_to_catalog( catalog, L"winetest.inf" );
522 ret = CryptCATPersistStore( catalog );
523 todo_wine
524 ok( ret, "Failed to write catalog, error %u\n", GetLastError() );
526 ret = CryptCATClose( catalog );
527 ok( ret, "Failed to close catalog, error %u\n", GetLastError() );
529 if (!(cert = testsign_sign( L"winetest.cat" )))
531 ret = DeleteFileW( L"winetest.cat" );
532 ok( ret, "Failed to delete file, error %u\n", GetLastError() );
533 ret = DeleteFileW( L"winetest.inf" );
534 ok( ret, "Failed to delete file, error %u\n", GetLastError() );
535 ret = DeleteFileW( L"winetest.sys" );
536 ok( ret, "Failed to delete file, error %u\n", GetLastError() );
537 return FALSE;
540 /* Install the driver. */
542 set = SetupDiCreateDeviceInfoList( NULL, NULL );
543 ok( set != INVALID_HANDLE_VALUE, "failed to create device list, error %u\n", GetLastError() );
545 ret = SetupDiCreateDeviceInfoW( set, L"root\\winetest\\0", &GUID_NULL, NULL, NULL, 0, &device );
546 ok( ret, "failed to create device, error %#x\n", GetLastError() );
548 ret = SetupDiSetDeviceRegistryPropertyW( set, &device, SPDRP_HARDWAREID, (const BYTE *)hardware_id,
549 sizeof(hardware_id) );
550 ok( ret, "failed to create set hardware ID, error %u\n", GetLastError() );
552 ret = SetupDiCallClassInstaller( DIF_REGISTERDEVICE, set, &device );
553 ok( ret, "failed to register device, error %u\n", GetLastError() );
555 ret = SetupDiDestroyDeviceInfoList( set );
556 ok( ret, "failed to destroy set, error %u\n", GetLastError() );
558 GetFullPathNameW( L"winetest.inf", ARRAY_SIZE(path), path, NULL );
560 ret = UpdateDriverForPlugAndPlayDevicesW( NULL, hardware_id, path, INSTALLFLAG_FORCE, &need_reboot );
561 ok( ret, "failed to install device, error %u\n", GetLastError() );
562 ok( !need_reboot, "expected no reboot necessary\n" );
564 testsign_cleanup( cert );
566 /* Check that the service is created and started. */
567 manager = OpenSCManagerW( NULL, NULL, SC_MANAGER_CONNECT );
568 ok( !!manager, "failed to open service manager, error %u\n", GetLastError() );
570 service = OpenServiceW( manager, L"winetest", SERVICE_START );
571 ok( !!service, "failed to open service, error %u\n", GetLastError() );
573 ret = StartServiceW( service, 0, NULL );
574 ok( !ret, "service didn't start automatically\n" );
575 if (!ret && GetLastError() != ERROR_SERVICE_ALREADY_RUNNING)
577 /* If Secure Boot is enabled or the machine is 64-bit, it will reject an unsigned driver. */
578 ok( GetLastError() == ERROR_DRIVER_BLOCKED || GetLastError() == ERROR_INVALID_IMAGE_HASH,
579 "unexpected error %u\n", GetLastError() );
580 win_skip( "Failed to start service; probably your machine doesn't accept unsigned drivers.\n" );
583 CloseServiceHandle( service );
584 CloseServiceHandle( manager );
585 return ret || GetLastError() == ERROR_SERVICE_ALREADY_RUNNING;
588 #define check_member_( file, line, val, exp, fmt, member ) \
589 ok_( file, line )((val).member == (exp).member, "got " #member " " fmt ", expected " fmt "\n", \
590 (val).member, (exp).member)
591 #define check_member( val, exp, fmt, member ) \
592 check_member_( __FILE__, __LINE__, val, exp, fmt, member )
594 #define check_member_guid_( file, line, val, exp, member ) \
595 ok_( file, line )(IsEqualGUID( &(val).member, &(exp).member ), "got " #member " %s, expected %s\n", \
596 debugstr_guid( &(val).member ), debugstr_guid( &(exp).member ))
597 #define check_member_guid( val, exp, member ) \
598 check_member_guid_( __FILE__, __LINE__, val, exp, member )
600 #define check_member_wstr_( file, line, val, exp, member ) \
601 ok_( file, line )(!wcscmp( (val).member, (exp).member ), "got " #member " %s, expected %s\n", \
602 debugstr_w((val).member), debugstr_w((exp).member))
603 #define check_member_wstr( val, exp, member ) \
604 check_member_wstr_( __FILE__, __LINE__, val, exp, member )
606 #define check_hidp_caps( a, b ) check_hidp_caps_( __LINE__, a, b )
607 static inline void check_hidp_caps_( int line, HIDP_CAPS *caps, const HIDP_CAPS *exp )
609 check_member_( __FILE__, line, *caps, *exp, "%04x", Usage );
610 check_member_( __FILE__, line, *caps, *exp, "%04x", UsagePage );
611 check_member_( __FILE__, line, *caps, *exp, "%d", InputReportByteLength );
612 check_member_( __FILE__, line, *caps, *exp, "%d", OutputReportByteLength );
613 check_member_( __FILE__, line, *caps, *exp, "%d", FeatureReportByteLength );
614 check_member_( __FILE__, line, *caps, *exp, "%d", NumberLinkCollectionNodes );
615 check_member_( __FILE__, line, *caps, *exp, "%d", NumberInputButtonCaps );
616 check_member_( __FILE__, line, *caps, *exp, "%d", NumberInputValueCaps );
617 check_member_( __FILE__, line, *caps, *exp, "%d", NumberInputDataIndices );
618 check_member_( __FILE__, line, *caps, *exp, "%d", NumberOutputButtonCaps );
619 check_member_( __FILE__, line, *caps, *exp, "%d", NumberOutputValueCaps );
620 check_member_( __FILE__, line, *caps, *exp, "%d", NumberOutputDataIndices );
621 check_member_( __FILE__, line, *caps, *exp, "%d", NumberFeatureButtonCaps );
622 check_member_( __FILE__, line, *caps, *exp, "%d", NumberFeatureValueCaps );
623 check_member_( __FILE__, line, *caps, *exp, "%d", NumberFeatureDataIndices );
626 #define check_hidp_link_collection_node( a, b ) check_hidp_link_collection_node_( __LINE__, a, b )
627 static inline void check_hidp_link_collection_node_( int line, HIDP_LINK_COLLECTION_NODE *node,
628 const HIDP_LINK_COLLECTION_NODE *exp )
630 check_member_( __FILE__, line, *node, *exp, "%04x", LinkUsage );
631 check_member_( __FILE__, line, *node, *exp, "%04x", LinkUsagePage );
632 check_member_( __FILE__, line, *node, *exp, "%d", Parent );
633 check_member_( __FILE__, line, *node, *exp, "%d", NumberOfChildren );
634 check_member_( __FILE__, line, *node, *exp, "%d", NextSibling );
635 check_member_( __FILE__, line, *node, *exp, "%d", FirstChild );
636 check_member_( __FILE__, line, *node, *exp, "%d", CollectionType );
637 check_member_( __FILE__, line, *node, *exp, "%d", IsAlias );
640 #define check_hidp_button_caps( a, b ) check_hidp_button_caps_( __LINE__, a, b )
641 static inline void check_hidp_button_caps_( int line, HIDP_BUTTON_CAPS *caps, const HIDP_BUTTON_CAPS *exp )
643 check_member_( __FILE__, line, *caps, *exp, "%04x", UsagePage );
644 check_member_( __FILE__, line, *caps, *exp, "%d", ReportID );
645 check_member_( __FILE__, line, *caps, *exp, "%d", IsAlias );
646 check_member_( __FILE__, line, *caps, *exp, "%d", BitField );
647 check_member_( __FILE__, line, *caps, *exp, "%d", LinkCollection );
648 check_member_( __FILE__, line, *caps, *exp, "%04x", LinkUsage );
649 check_member_( __FILE__, line, *caps, *exp, "%04x", LinkUsagePage );
650 check_member_( __FILE__, line, *caps, *exp, "%d", IsRange );
651 check_member_( __FILE__, line, *caps, *exp, "%d", IsStringRange );
652 check_member_( __FILE__, line, *caps, *exp, "%d", IsDesignatorRange );
653 check_member_( __FILE__, line, *caps, *exp, "%d", IsAbsolute );
655 if (!caps->IsRange && !exp->IsRange)
657 check_member_( __FILE__, line, *caps, *exp, "%04x", NotRange.Usage );
658 check_member_( __FILE__, line, *caps, *exp, "%d", NotRange.DataIndex );
660 else if (caps->IsRange && exp->IsRange)
662 check_member_( __FILE__, line, *caps, *exp, "%04x", Range.UsageMin );
663 check_member_( __FILE__, line, *caps, *exp, "%04x", Range.UsageMax );
664 check_member_( __FILE__, line, *caps, *exp, "%d", Range.DataIndexMin );
665 check_member_( __FILE__, line, *caps, *exp, "%d", Range.DataIndexMax );
668 if (!caps->IsRange && !exp->IsRange)
669 check_member_( __FILE__, line, *caps, *exp, "%d", NotRange.StringIndex );
670 else if (caps->IsStringRange && exp->IsStringRange)
672 check_member_( __FILE__, line, *caps, *exp, "%d", Range.StringMin );
673 check_member_( __FILE__, line, *caps, *exp, "%d", Range.StringMax );
676 if (!caps->IsDesignatorRange && !exp->IsDesignatorRange)
677 check_member_( __FILE__, line, *caps, *exp, "%d", NotRange.DesignatorIndex );
678 else if (caps->IsDesignatorRange && exp->IsDesignatorRange)
680 check_member_( __FILE__, line, *caps, *exp, "%d", Range.DesignatorMin );
681 check_member_( __FILE__, line, *caps, *exp, "%d", Range.DesignatorMax );
685 #define check_hidp_value_caps( a, b ) check_hidp_value_caps_( __LINE__, a, b )
686 static inline void check_hidp_value_caps_( int line, HIDP_VALUE_CAPS *caps, const HIDP_VALUE_CAPS *exp )
688 check_member_( __FILE__, line, *caps, *exp, "%04x", UsagePage );
689 check_member_( __FILE__, line, *caps, *exp, "%d", ReportID );
690 check_member_( __FILE__, line, *caps, *exp, "%d", IsAlias );
691 check_member_( __FILE__, line, *caps, *exp, "%d", BitField );
692 check_member_( __FILE__, line, *caps, *exp, "%d", LinkCollection );
693 check_member_( __FILE__, line, *caps, *exp, "%d", LinkUsage );
694 check_member_( __FILE__, line, *caps, *exp, "%d", LinkUsagePage );
695 check_member_( __FILE__, line, *caps, *exp, "%d", IsRange );
696 check_member_( __FILE__, line, *caps, *exp, "%d", IsStringRange );
697 check_member_( __FILE__, line, *caps, *exp, "%d", IsDesignatorRange );
698 check_member_( __FILE__, line, *caps, *exp, "%d", IsAbsolute );
700 check_member_( __FILE__, line, *caps, *exp, "%d", HasNull );
701 check_member_( __FILE__, line, *caps, *exp, "%d", BitSize );
702 check_member_( __FILE__, line, *caps, *exp, "%d", ReportCount );
703 check_member_( __FILE__, line, *caps, *exp, "%d", UnitsExp );
704 check_member_( __FILE__, line, *caps, *exp, "%d", Units );
705 check_member_( __FILE__, line, *caps, *exp, "%d", LogicalMin );
706 check_member_( __FILE__, line, *caps, *exp, "%d", LogicalMax );
707 check_member_( __FILE__, line, *caps, *exp, "%d", PhysicalMin );
708 check_member_( __FILE__, line, *caps, *exp, "%d", PhysicalMax );
710 if (!caps->IsRange && !exp->IsRange)
712 check_member_( __FILE__, line, *caps, *exp, "%04x", NotRange.Usage );
713 check_member_( __FILE__, line, *caps, *exp, "%d", NotRange.DataIndex );
715 else if (caps->IsRange && exp->IsRange)
717 check_member_( __FILE__, line, *caps, *exp, "%04x", Range.UsageMin );
718 check_member_( __FILE__, line, *caps, *exp, "%04x", Range.UsageMax );
719 check_member_( __FILE__, line, *caps, *exp, "%d", Range.DataIndexMin );
720 check_member_( __FILE__, line, *caps, *exp, "%d", Range.DataIndexMax );
723 if (!caps->IsRange && !exp->IsRange)
724 check_member_( __FILE__, line, *caps, *exp, "%d", NotRange.StringIndex );
725 else if (caps->IsStringRange && exp->IsStringRange)
727 check_member_( __FILE__, line, *caps, *exp, "%d", Range.StringMin );
728 check_member_( __FILE__, line, *caps, *exp, "%d", Range.StringMax );
731 if (!caps->IsDesignatorRange && !exp->IsDesignatorRange)
732 check_member_( __FILE__, line, *caps, *exp, "%d", NotRange.DesignatorIndex );
733 else if (caps->IsDesignatorRange && exp->IsDesignatorRange)
735 check_member_( __FILE__, line, *caps, *exp, "%d", Range.DesignatorMin );
736 check_member_( __FILE__, line, *caps, *exp, "%d", Range.DesignatorMax );
740 static BOOL sync_ioctl( HANDLE file, DWORD code, void *in_buf, DWORD in_len, void *out_buf, DWORD *ret_len )
742 OVERLAPPED ovl = {0};
743 DWORD out_len = ret_len ? *ret_len : 0;
744 BOOL ret;
746 ovl.hEvent = CreateEventW( NULL, TRUE, FALSE, NULL );
747 ret = DeviceIoControl( file, code, in_buf, in_len, out_buf, out_len, &out_len, &ovl );
748 if (!ret && GetLastError() == ERROR_IO_PENDING)
749 ret = GetOverlappedResult( file, &ovl, &out_len, TRUE );
750 CloseHandle( ovl.hEvent );
752 if (ret_len) *ret_len = out_len;
753 return ret;
756 #define set_hid_expect( a, b, c ) set_hid_expect_( __LINE__, a, b, c )
757 static void set_hid_expect_( int line, HANDLE file, struct hid_expect *expect, DWORD expect_size )
759 const char *source_file;
760 BOOL ret;
761 int i;
763 source_file = strrchr( __FILE__, '/' );
764 if (!source_file) source_file = strrchr( __FILE__, '\\' );
765 if (!source_file) source_file = __FILE__;
766 else source_file++;
768 for (i = 0; i < expect_size / sizeof(struct hid_expect); ++i)
769 snprintf( expect[i].context, ARRAY_SIZE(expect[i].context), "%s:%d", source_file, line );
771 ret = sync_ioctl( file, IOCTL_WINETEST_HID_SET_EXPECT, expect, expect_size, NULL, 0 );
772 ok( ret, "IOCTL_WINETEST_HID_SET_EXPECT failed, last error %u\n", GetLastError() );
775 #define send_hid_input( a, b, c ) send_hid_input_( __LINE__, a, b, c )
776 static void send_hid_input_( int line, HANDLE file, struct hid_expect *expect, DWORD expect_size )
778 const char *source_file;
779 BOOL ret;
780 int i;
782 source_file = strrchr( __FILE__, '/' );
783 if (!source_file) source_file = strrchr( __FILE__, '\\' );
784 if (!source_file) source_file = __FILE__;
785 else source_file++;
787 for (i = 0; i < expect_size / sizeof(struct hid_expect); ++i)
788 snprintf( expect[i].context, ARRAY_SIZE(expect[i].context), "%s:%d", source_file, line );
790 ret = sync_ioctl( file, IOCTL_WINETEST_HID_SEND_INPUT, expect, expect_size, NULL, 0 );
791 ok( ret, "IOCTL_WINETEST_HID_SEND_INPUT failed, last error %u\n", GetLastError() );
794 static void test_hidp_get_input( HANDLE file, int report_id, ULONG report_len, PHIDP_PREPARSED_DATA preparsed )
796 struct hid_expect expect[] =
799 .code = IOCTL_HID_GET_INPUT_REPORT,
800 .report_id = report_id,
801 .report_len = report_len - (report_id ? 0 : 1),
802 .report_buf = {report_id ? report_id : 0xa5,0xa5,2},
803 .ret_length = 3,
804 .ret_status = STATUS_SUCCESS,
807 .code = IOCTL_HID_GET_INPUT_REPORT,
808 .report_id = report_id,
809 .report_len = 2 * report_len - (report_id ? 0 : 1),
810 .report_buf = {report_id ? report_id : 0xa5,0xa5,1},
811 .ret_length = 3,
812 .ret_status = STATUS_SUCCESS,
816 char buffer[200], report[200];
817 NTSTATUS status;
818 ULONG length;
819 BOOL ret;
821 memset( report, 0xcd, sizeof(report) );
822 status = HidP_InitializeReportForID( HidP_Input, report_id, preparsed, report, report_len );
823 ok( status == HIDP_STATUS_SUCCESS, "HidP_InitializeReportForID returned %#x\n", status );
825 SetLastError( 0xdeadbeef );
826 ret = HidD_GetInputReport( file, report, 0 );
827 ok( !ret, "HidD_GetInputReport succeeded\n" );
828 ok( GetLastError() == ERROR_INVALID_USER_BUFFER, "HidD_GetInputReport returned error %u\n", GetLastError() );
830 SetLastError( 0xdeadbeef );
831 ret = HidD_GetInputReport( file, report, report_len - 1 );
832 ok( !ret, "HidD_GetInputReport succeeded\n" );
833 ok( GetLastError() == ERROR_INVALID_PARAMETER || broken( GetLastError() == ERROR_CRC ),
834 "HidD_GetInputReport returned error %u\n", GetLastError() );
836 if (!report_id)
838 struct hid_expect broken_expect =
840 .code = IOCTL_HID_GET_INPUT_REPORT,
841 .broken = TRUE,
842 .report_len = report_len - 1,
843 .report_buf =
845 0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
846 0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
847 0x5a,0x5a,0x5a,0x5a,0x5a,
849 .ret_length = 3,
850 .ret_status = STATUS_SUCCESS,
853 set_hid_expect( file, &broken_expect, sizeof(broken_expect) );
856 SetLastError( 0xdeadbeef );
857 memset( buffer, 0x5a, sizeof(buffer) );
858 ret = HidD_GetInputReport( file, buffer, report_len );
859 if (report_id || broken( !ret ) /* w7u */)
861 ok( !ret, "HidD_GetInputReport succeeded, last error %u\n", GetLastError() );
862 ok( GetLastError() == ERROR_INVALID_PARAMETER || broken( GetLastError() == ERROR_CRC ),
863 "HidD_GetInputReport returned error %u\n", GetLastError() );
865 else
867 ok( ret, "HidD_GetInputReport failed, last error %u\n", GetLastError() );
868 ok( buffer[0] == 0x5a, "got buffer[0] %x, expected 0x5a\n", (BYTE)buffer[0] );
871 set_hid_expect( file, expect, sizeof(expect) );
873 SetLastError( 0xdeadbeef );
874 ret = HidD_GetInputReport( file, report, report_len );
875 ok( ret, "HidD_GetInputReport failed, last error %u\n", GetLastError() );
876 ok( report[0] == report_id, "got report[0] %02x, expected %02x\n", report[0], report_id );
878 SetLastError( 0xdeadbeef );
879 length = report_len * 2;
880 ret = sync_ioctl( file, IOCTL_HID_GET_INPUT_REPORT, NULL, 0, report, &length );
881 ok( ret, "IOCTL_HID_GET_INPUT_REPORT failed, last error %u\n", GetLastError() );
882 ok( length == 3, "got length %u, expected 3\n", length );
883 ok( report[0] == report_id, "got report[0] %02x, expected %02x\n", report[0], report_id );
885 set_hid_expect( file, NULL, 0 );
888 static void test_hidp_get_feature( HANDLE file, int report_id, ULONG report_len, PHIDP_PREPARSED_DATA preparsed )
890 struct hid_expect expect[] =
893 .code = IOCTL_HID_GET_FEATURE,
894 .report_id = report_id,
895 .report_len = report_len - (report_id ? 0 : 1),
896 .report_buf = {report_id ? report_id : 0xa5,0xa5,0xa5},
897 .ret_length = 3,
898 .ret_status = STATUS_SUCCESS,
901 .code = IOCTL_HID_GET_FEATURE,
902 .report_id = report_id,
903 .report_len = 2 * report_len - (report_id ? 0 : 1),
904 .report_buf = {report_id ? report_id : 0xa5,0xa5,0xa5},
905 .ret_length = 3,
906 .ret_status = STATUS_SUCCESS,
910 char buffer[200], report[200];
911 NTSTATUS status;
912 ULONG length;
913 BOOL ret;
915 memset( report, 0xcd, sizeof(report) );
916 status = HidP_InitializeReportForID( HidP_Feature, report_id, preparsed, report, report_len );
917 ok( status == HIDP_STATUS_SUCCESS, "HidP_InitializeReportForID returned %#x\n", status );
919 SetLastError( 0xdeadbeef );
920 ret = HidD_GetFeature( file, report, 0 );
921 ok( !ret, "HidD_GetFeature succeeded\n" );
922 ok( GetLastError() == ERROR_INVALID_USER_BUFFER, "HidD_GetFeature returned error %u\n", GetLastError() );
924 SetLastError( 0xdeadbeef );
925 ret = HidD_GetFeature( file, report, report_len - 1 );
926 ok( !ret, "HidD_GetFeature succeeded\n" );
927 ok( GetLastError() == ERROR_INVALID_PARAMETER || broken( GetLastError() == ERROR_CRC ),
928 "HidD_GetFeature returned error %u\n", GetLastError() );
930 if (!report_id)
932 struct hid_expect broken_expect =
934 .code = IOCTL_HID_GET_FEATURE,
935 .broken = TRUE,
936 .report_len = report_len - 1,
937 .report_buf =
939 0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
940 0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
941 0x5a,0x5a,0x5a,0x5a,0x5a,
943 .ret_length = 3,
944 .ret_status = STATUS_SUCCESS,
947 set_hid_expect( file, &broken_expect, sizeof(broken_expect) );
950 SetLastError( 0xdeadbeef );
951 memset( buffer, 0x5a, sizeof(buffer) );
952 ret = HidD_GetFeature( file, buffer, report_len );
953 if (report_id || broken( !ret ))
955 ok( !ret, "HidD_GetFeature succeeded, last error %u\n", GetLastError() );
956 ok( GetLastError() == ERROR_INVALID_PARAMETER || broken( GetLastError() == ERROR_CRC ),
957 "HidD_GetFeature returned error %u\n", GetLastError() );
959 else
961 ok( ret, "HidD_GetFeature failed, last error %u\n", GetLastError() );
962 ok( buffer[0] == 0x5a, "got buffer[0] %x, expected 0x5a\n", (BYTE)buffer[0] );
965 set_hid_expect( file, expect, sizeof(expect) );
967 SetLastError( 0xdeadbeef );
968 ret = HidD_GetFeature( file, report, report_len );
969 ok( ret, "HidD_GetFeature failed, last error %u\n", GetLastError() );
970 ok( report[0] == report_id, "got report[0] %02x, expected %02x\n", report[0], report_id );
972 length = report_len * 2;
973 SetLastError( 0xdeadbeef );
974 ret = sync_ioctl( file, IOCTL_HID_GET_FEATURE, NULL, 0, report, &length );
975 ok( ret, "IOCTL_HID_GET_FEATURE failed, last error %u\n", GetLastError() );
976 ok( length == 3, "got length %u, expected 3\n", length );
977 ok( report[0] == report_id, "got report[0] %02x, expected %02x\n", report[0], report_id );
979 set_hid_expect( file, NULL, 0 );
982 static void test_hidp_set_feature( HANDLE file, int report_id, ULONG report_len, PHIDP_PREPARSED_DATA preparsed )
984 struct hid_expect expect[] =
987 .code = IOCTL_HID_SET_FEATURE,
988 .report_id = report_id,
989 .report_len = report_len - (report_id ? 0 : 1),
990 .report_buf = {report_id},
991 .ret_length = 3,
992 .ret_status = STATUS_SUCCESS,
995 .code = IOCTL_HID_SET_FEATURE,
996 .report_id = report_id,
997 .report_len = report_len - (report_id ? 0 : 1),
998 .report_buf =
1000 report_id,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1001 0,0,0,0,0,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,
1002 0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,
1004 .ret_length = 3,
1005 .ret_status = STATUS_SUCCESS,
1008 char buffer[200], report[200];
1009 NTSTATUS status;
1010 ULONG length;
1011 BOOL ret;
1013 memset( report, 0xcd, sizeof(report) );
1014 status = HidP_InitializeReportForID( HidP_Feature, report_id, preparsed, report, report_len );
1015 ok( status == HIDP_STATUS_SUCCESS, "HidP_InitializeReportForID returned %#x\n", status );
1017 SetLastError( 0xdeadbeef );
1018 ret = HidD_SetFeature( file, report, 0 );
1019 ok( !ret, "HidD_SetFeature succeeded\n" );
1020 ok( GetLastError() == ERROR_INVALID_USER_BUFFER, "HidD_SetFeature returned error %u\n", GetLastError() );
1022 SetLastError( 0xdeadbeef );
1023 ret = HidD_SetFeature( file, report, report_len - 1 );
1024 ok( !ret, "HidD_SetFeature succeeded\n" );
1025 ok( GetLastError() == ERROR_INVALID_PARAMETER || broken( GetLastError() == ERROR_CRC ),
1026 "HidD_SetFeature returned error %u\n", GetLastError() );
1028 if (!report_id)
1030 struct hid_expect broken_expect =
1032 .code = IOCTL_HID_SET_FEATURE,
1033 .broken = TRUE,
1034 .report_len = report_len - 1,
1035 .report_buf =
1037 0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
1038 0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,
1039 0x5a,0x5a,0x5a,0x5a,0x5a,
1041 .ret_length = 3,
1042 .ret_status = STATUS_SUCCESS,
1045 set_hid_expect( file, &broken_expect, sizeof(broken_expect) );
1048 SetLastError( 0xdeadbeef );
1049 memset( buffer, 0x5a, sizeof(buffer) );
1050 ret = HidD_SetFeature( file, buffer, report_len );
1051 if (report_id || broken( !ret ))
1053 ok( !ret, "HidD_SetFeature succeeded, last error %u\n", GetLastError() );
1054 ok( GetLastError() == ERROR_INVALID_PARAMETER || broken( GetLastError() == ERROR_CRC ),
1055 "HidD_SetFeature returned error %u\n", GetLastError() );
1057 else
1059 ok( ret, "HidD_SetFeature failed, last error %u\n", GetLastError() );
1062 set_hid_expect( file, expect, sizeof(expect) );
1064 SetLastError( 0xdeadbeef );
1065 ret = HidD_SetFeature( file, report, report_len );
1066 ok( ret, "HidD_SetFeature failed, last error %u\n", GetLastError() );
1068 length = report_len * 2;
1069 SetLastError( 0xdeadbeef );
1070 ret = sync_ioctl( file, IOCTL_HID_SET_FEATURE, NULL, 0, report, &length );
1071 ok( !ret, "IOCTL_HID_SET_FEATURE succeeded\n" );
1072 ok( GetLastError() == ERROR_INVALID_USER_BUFFER, "IOCTL_HID_SET_FEATURE returned error %u\n",
1073 GetLastError() );
1074 length = 0;
1075 SetLastError( 0xdeadbeef );
1076 ret = sync_ioctl( file, IOCTL_HID_SET_FEATURE, report, report_len * 2, NULL, &length );
1077 ok( ret, "IOCTL_HID_SET_FEATURE failed, last error %u\n", GetLastError() );
1078 ok( length == 3, "got length %u, expected 3\n", length );
1080 set_hid_expect( file, NULL, 0 );
1083 static void test_hidp_set_output( HANDLE file, int report_id, ULONG report_len, PHIDP_PREPARSED_DATA preparsed )
1085 struct hid_expect expect[] =
1088 .code = IOCTL_HID_SET_OUTPUT_REPORT,
1089 .report_id = report_id,
1090 .report_len = report_len - (report_id ? 0 : 1),
1091 .report_buf = {report_id},
1092 .ret_length = 3,
1093 .ret_status = STATUS_SUCCESS,
1096 .code = IOCTL_HID_SET_OUTPUT_REPORT,
1097 .report_id = report_id,
1098 .report_len = report_len - (report_id ? 0 : 1),
1099 .report_buf = {report_id,0,0xcd,0xcd,0xcd},
1100 .ret_length = 3,
1101 .ret_status = STATUS_SUCCESS,
1105 char buffer[200], report[200];
1106 NTSTATUS status;
1107 ULONG length;
1108 BOOL ret;
1110 memset( report, 0xcd, sizeof(report) );
1111 status = HidP_InitializeReportForID( HidP_Output, report_id, preparsed, report, report_len );
1112 ok( status == HIDP_STATUS_REPORT_DOES_NOT_EXIST, "HidP_InitializeReportForID returned %#x\n", status );
1113 memset( report, 0, report_len );
1114 report[0] = report_id;
1116 SetLastError( 0xdeadbeef );
1117 ret = HidD_SetOutputReport( file, report, 0 );
1118 ok( !ret, "HidD_SetOutputReport succeeded\n" );
1119 ok( GetLastError() == ERROR_INVALID_USER_BUFFER, "HidD_SetOutputReport returned error %u\n",
1120 GetLastError() );
1122 SetLastError( 0xdeadbeef );
1123 ret = HidD_SetOutputReport( file, report, report_len - 1 );
1124 ok( !ret, "HidD_SetOutputReport succeeded\n" );
1125 ok( GetLastError() == ERROR_INVALID_PARAMETER || broken( GetLastError() == ERROR_CRC ),
1126 "HidD_SetOutputReport returned error %u\n", GetLastError() );
1128 if (!report_id)
1130 struct hid_expect broken_expect =
1132 .code = IOCTL_HID_SET_OUTPUT_REPORT,
1133 .broken = TRUE,
1134 .report_len = report_len - 1,
1135 .report_buf = {0x5a,0x5a},
1136 .ret_length = 3,
1137 .ret_status = STATUS_SUCCESS,
1140 set_hid_expect( file, &broken_expect, sizeof(broken_expect) );
1143 SetLastError( 0xdeadbeef );
1144 memset( buffer, 0x5a, sizeof(buffer) );
1145 ret = HidD_SetOutputReport( file, buffer, report_len );
1146 if (report_id || broken( !ret ))
1148 ok( !ret, "HidD_SetOutputReport succeeded, last error %u\n", GetLastError() );
1149 ok( GetLastError() == ERROR_INVALID_PARAMETER || broken( GetLastError() == ERROR_CRC ),
1150 "HidD_SetOutputReport returned error %u\n", GetLastError() );
1152 else
1154 ok( ret, "HidD_SetOutputReport failed, last error %u\n", GetLastError() );
1157 set_hid_expect( file, expect, sizeof(expect) );
1159 SetLastError( 0xdeadbeef );
1160 ret = HidD_SetOutputReport( file, report, report_len );
1161 ok( ret, "HidD_SetOutputReport failed, last error %u\n", GetLastError() );
1163 length = report_len * 2;
1164 SetLastError( 0xdeadbeef );
1165 ret = sync_ioctl( file, IOCTL_HID_SET_OUTPUT_REPORT, NULL, 0, report, &length );
1166 ok( !ret, "IOCTL_HID_SET_OUTPUT_REPORT succeeded\n" );
1167 ok( GetLastError() == ERROR_INVALID_USER_BUFFER,
1168 "IOCTL_HID_SET_OUTPUT_REPORT returned error %u\n", GetLastError() );
1169 length = 0;
1170 SetLastError( 0xdeadbeef );
1171 ret = sync_ioctl( file, IOCTL_HID_SET_OUTPUT_REPORT, report, report_len * 2, NULL, &length );
1172 ok( ret, "IOCTL_HID_SET_OUTPUT_REPORT failed, last error %u\n", GetLastError() );
1173 ok( length == 3, "got length %u, expected 3\n", length );
1175 set_hid_expect( file, NULL, 0 );
1178 static void test_write_file( HANDLE file, int report_id, ULONG report_len )
1180 struct hid_expect expect =
1182 .code = IOCTL_HID_WRITE_REPORT,
1183 .report_id = report_id,
1184 .report_len = report_len - (report_id ? 0 : 1),
1185 .report_buf = {report_id ? report_id : 0xcd,0xcd,0xcd,0xcd,0xcd},
1186 .ret_length = 3,
1187 .ret_status = STATUS_SUCCESS,
1190 char report[200];
1191 ULONG length;
1192 BOOL ret;
1194 SetLastError( 0xdeadbeef );
1195 ret = WriteFile( file, report, 0, &length, NULL );
1196 ok( !ret, "WriteFile succeeded\n" );
1197 ok( GetLastError() == ERROR_INVALID_USER_BUFFER, "WriteFile returned error %u\n", GetLastError() );
1198 ok( length == 0, "WriteFile returned %x\n", length );
1199 SetLastError( 0xdeadbeef );
1200 ret = WriteFile( file, report, report_len - 1, &length, NULL );
1201 ok( !ret, "WriteFile succeeded\n" );
1202 ok( GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_INVALID_USER_BUFFER,
1203 "WriteFile returned error %u\n", GetLastError() );
1204 ok( length == 0, "WriteFile returned %x\n", length );
1206 set_hid_expect( file, &expect, sizeof(expect) );
1208 memset( report, 0xcd, sizeof(report) );
1209 report[0] = 0xa5;
1210 SetLastError( 0xdeadbeef );
1211 ret = WriteFile( file, report, report_len * 2, &length, NULL );
1212 if (report_id || broken( !ret ) /* w7u */)
1214 ok( !ret, "WriteFile succeeded\n" );
1215 ok( GetLastError() == ERROR_INVALID_PARAMETER, "WriteFile returned error %u\n", GetLastError() );
1216 ok( length == 0, "WriteFile wrote %u\n", length );
1217 SetLastError( 0xdeadbeef );
1218 report[0] = report_id;
1219 ret = WriteFile( file, report, report_len, &length, NULL );
1222 if (report_id)
1224 ok( ret, "WriteFile failed, last error %u\n", GetLastError() );
1225 ok( length == 2, "WriteFile wrote %u\n", length );
1227 else
1229 ok( ret, "WriteFile failed, last error %u\n", GetLastError() );
1230 ok( length == 3, "WriteFile wrote %u\n", length );
1233 set_hid_expect( file, NULL, 0 );
1236 static void test_hidp( HANDLE file, HANDLE async_file, int report_id, BOOL polled, const HIDP_CAPS *expect_caps )
1238 const HIDP_BUTTON_CAPS expect_button_caps[] =
1241 .UsagePage = HID_USAGE_PAGE_BUTTON,
1242 .ReportID = report_id,
1243 .BitField = 2,
1244 .LinkUsage = HID_USAGE_GENERIC_JOYSTICK,
1245 .LinkUsagePage = HID_USAGE_PAGE_GENERIC,
1246 .LinkCollection = 1,
1247 .IsRange = TRUE,
1248 .IsAbsolute = TRUE,
1249 .Range.UsageMin = 1,
1250 .Range.UsageMax = 8,
1251 .Range.DataIndexMin = 2,
1252 .Range.DataIndexMax = 9,
1255 .UsagePage = HID_USAGE_PAGE_BUTTON,
1256 .ReportID = report_id,
1257 .BitField = 3,
1258 .LinkCollection = 1,
1259 .LinkUsage = HID_USAGE_GENERIC_JOYSTICK,
1260 .LinkUsagePage = HID_USAGE_PAGE_GENERIC,
1261 .IsRange = TRUE,
1262 .IsAbsolute = TRUE,
1263 .Range.UsageMin = 0x18,
1264 .Range.UsageMax = 0x1f,
1265 .Range.DataIndexMin = 10,
1266 .Range.DataIndexMax = 17,
1269 .UsagePage = HID_USAGE_PAGE_KEYBOARD,
1270 .ReportID = report_id,
1271 .BitField = 0x1fc,
1272 .LinkCollection = 1,
1273 .LinkUsage = HID_USAGE_GENERIC_JOYSTICK,
1274 .LinkUsagePage = HID_USAGE_PAGE_GENERIC,
1275 .IsRange = TRUE,
1276 .IsAbsolute = FALSE,
1277 .Range.UsageMin = 0x8,
1278 .Range.UsageMax = 0xf,
1279 .Range.DataIndexMin = 18,
1280 .Range.DataIndexMax = 25,
1283 .UsagePage = HID_USAGE_PAGE_BUTTON,
1284 .ReportID = report_id,
1285 .BitField = 2,
1286 .LinkCollection = 1,
1287 .LinkUsage = HID_USAGE_GENERIC_JOYSTICK,
1288 .LinkUsagePage = HID_USAGE_PAGE_GENERIC,
1289 .IsRange = FALSE,
1290 .IsAbsolute = TRUE,
1291 .NotRange.Usage = 0x20,
1292 .NotRange.Reserved1 = 0x20,
1293 .NotRange.DataIndex = 26,
1294 .NotRange.Reserved4 = 26,
1297 const HIDP_VALUE_CAPS expect_value_caps[] =
1300 .UsagePage = HID_USAGE_PAGE_GENERIC,
1301 .ReportID = report_id,
1302 .BitField = 2,
1303 .LinkUsage = HID_USAGE_GENERIC_JOYSTICK,
1304 .LinkUsagePage = HID_USAGE_PAGE_GENERIC,
1305 .LinkCollection = 1,
1306 .IsAbsolute = TRUE,
1307 .BitSize = 8,
1308 .ReportCount = 1,
1309 .LogicalMin = -128,
1310 .LogicalMax = 127,
1311 .NotRange.Usage = HID_USAGE_GENERIC_Y,
1312 .NotRange.Reserved1 = HID_USAGE_GENERIC_Y,
1315 .UsagePage = HID_USAGE_PAGE_GENERIC,
1316 .ReportID = report_id,
1317 .BitField = 2,
1318 .LinkUsage = HID_USAGE_GENERIC_JOYSTICK,
1319 .LinkUsagePage = HID_USAGE_PAGE_GENERIC,
1320 .LinkCollection = 1,
1321 .IsAbsolute = TRUE,
1322 .BitSize = 8,
1323 .ReportCount = 1,
1324 .LogicalMin = -128,
1325 .LogicalMax = 127,
1326 .NotRange.Usage = HID_USAGE_GENERIC_X,
1327 .NotRange.Reserved1 = HID_USAGE_GENERIC_X,
1328 .NotRange.DataIndex = 1,
1329 .NotRange.Reserved4 = 1,
1332 .UsagePage = HID_USAGE_PAGE_BUTTON,
1333 .ReportID = report_id,
1334 .BitField = 2,
1335 .LinkUsage = HID_USAGE_GENERIC_JOYSTICK,
1336 .LinkUsagePage = HID_USAGE_PAGE_GENERIC,
1337 .LinkCollection = 1,
1338 .IsAbsolute = TRUE,
1339 .ReportCount = 1,
1340 .LogicalMax = 1,
1341 .IsRange = TRUE,
1342 .Range.UsageMin = 0x21,
1343 .Range.UsageMax = 0x22,
1344 .Range.DataIndexMin = 27,
1345 .Range.DataIndexMax = 28,
1348 .UsagePage = HID_USAGE_PAGE_GENERIC,
1349 .ReportID = report_id,
1350 .BitField = 2,
1351 .LinkUsage = HID_USAGE_GENERIC_JOYSTICK,
1352 .LinkUsagePage = HID_USAGE_PAGE_GENERIC,
1353 .LinkCollection = 1,
1354 .IsAbsolute = TRUE,
1355 .BitSize = 4,
1356 .ReportCount = 2,
1357 .LogicalMin = 1,
1358 .LogicalMax = 8,
1359 .NotRange.Usage = HID_USAGE_GENERIC_HATSWITCH,
1360 .NotRange.Reserved1 = HID_USAGE_GENERIC_HATSWITCH,
1361 .NotRange.DataIndex = 29,
1362 .NotRange.Reserved4 = 29,
1365 static const HIDP_LINK_COLLECTION_NODE expect_collections[] =
1368 .LinkUsage = HID_USAGE_GENERIC_JOYSTICK,
1369 .LinkUsagePage = HID_USAGE_PAGE_GENERIC,
1370 .CollectionType = 1,
1371 .NumberOfChildren = 7,
1372 .FirstChild = 9,
1375 .LinkUsage = HID_USAGE_GENERIC_JOYSTICK,
1376 .LinkUsagePage = HID_USAGE_PAGE_GENERIC,
1377 .CollectionType = 2,
1380 static const HIDP_DATA expect_data[] =
1382 { .DataIndex = 0, },
1383 { .DataIndex = 1, },
1384 { .DataIndex = 5, .RawValue = 1, },
1385 { .DataIndex = 7, .RawValue = 1, },
1386 { .DataIndex = 19, .RawValue = 1, },
1387 { .DataIndex = 21, .RawValue = 1, },
1388 { .DataIndex = 30, },
1389 { .DataIndex = 31, },
1390 { .DataIndex = 32, .RawValue = 0xfeedcafe, },
1391 { .DataIndex = 37, .RawValue = 1, },
1392 { .DataIndex = 39, .RawValue = 1, },
1395 OVERLAPPED overlapped = {0}, overlapped2 = {0};
1396 HIDP_LINK_COLLECTION_NODE collections[16];
1397 PHIDP_PREPARSED_DATA preparsed_data;
1398 USAGE_AND_PAGE usage_and_pages[16];
1399 HIDP_BUTTON_CAPS button_caps[32];
1400 HIDP_VALUE_CAPS value_caps[16];
1401 char buffer[200], report[200];
1402 DWORD collection_count;
1403 DWORD waveform_list;
1404 HIDP_DATA data[64];
1405 USAGE usages[16];
1406 ULONG off, value;
1407 NTSTATUS status;
1408 HIDP_CAPS caps;
1409 unsigned int i;
1410 USHORT count;
1411 BOOL ret;
1413 ret = HidD_GetPreparsedData( file, &preparsed_data );
1414 ok( ret, "HidD_GetPreparsedData failed with error %u\n", GetLastError() );
1416 memset( buffer, 0, sizeof(buffer) );
1417 status = HidP_GetCaps( (PHIDP_PREPARSED_DATA)buffer, &caps );
1418 ok( status == HIDP_STATUS_INVALID_PREPARSED_DATA, "HidP_GetCaps returned %#x\n", status );
1419 status = HidP_GetCaps( preparsed_data, &caps );
1420 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetCaps returned %#x\n", status );
1421 check_hidp_caps( &caps, expect_caps );
1423 collection_count = 0;
1424 status = HidP_GetLinkCollectionNodes( collections, &collection_count, preparsed_data );
1425 ok( status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_GetLinkCollectionNodes returned %#x\n", status );
1426 ok( collection_count == caps.NumberLinkCollectionNodes,
1427 "got %d collection nodes, expected %d\n", collection_count, caps.NumberLinkCollectionNodes );
1428 collection_count = ARRAY_SIZE(collections);
1429 status = HidP_GetLinkCollectionNodes( collections, &collection_count, (PHIDP_PREPARSED_DATA)buffer );
1430 ok( status == HIDP_STATUS_INVALID_PREPARSED_DATA, "HidP_GetLinkCollectionNodes returned %#x\n", status );
1431 status = HidP_GetLinkCollectionNodes( collections, &collection_count, preparsed_data );
1432 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetLinkCollectionNodes returned %#x\n", status );
1433 ok( collection_count == caps.NumberLinkCollectionNodes,
1434 "got %d collection nodes, expected %d\n", collection_count, caps.NumberLinkCollectionNodes );
1436 for (i = 0; i < ARRAY_SIZE(expect_collections); ++i)
1438 winetest_push_context( "collections[%d]", i );
1439 check_hidp_link_collection_node( &collections[i], &expect_collections[i] );
1440 winetest_pop_context();
1443 count = ARRAY_SIZE(button_caps);
1444 status = HidP_GetButtonCaps( HidP_Output, button_caps, &count, preparsed_data );
1445 ok( status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetButtonCaps returned %#x\n", status );
1446 status = HidP_GetButtonCaps( HidP_Feature + 1, button_caps, &count, preparsed_data );
1447 ok( status == HIDP_STATUS_INVALID_REPORT_TYPE, "HidP_GetButtonCaps returned %#x\n", status );
1448 count = 0;
1449 status = HidP_GetButtonCaps( HidP_Input, button_caps, &count, preparsed_data );
1450 ok( status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_GetButtonCaps returned %#x\n", status );
1451 ok( count == caps.NumberInputButtonCaps, "HidP_GetButtonCaps returned count %d, expected %d\n",
1452 count, caps.NumberInputButtonCaps );
1453 count = ARRAY_SIZE(button_caps);
1454 status = HidP_GetButtonCaps( HidP_Input, button_caps, &count, (PHIDP_PREPARSED_DATA)buffer );
1455 ok( status == HIDP_STATUS_INVALID_PREPARSED_DATA, "HidP_GetButtonCaps returned %#x\n", status );
1456 memset( button_caps, 0, sizeof(button_caps) );
1457 status = HidP_GetButtonCaps( HidP_Input, button_caps, &count, preparsed_data );
1458 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetButtonCaps returned %#x\n", status );
1459 ok( count == caps.NumberInputButtonCaps, "HidP_GetButtonCaps returned count %d, expected %d\n",
1460 count, caps.NumberInputButtonCaps );
1462 for (i = 0; i < ARRAY_SIZE(expect_button_caps); ++i)
1464 winetest_push_context( "button_caps[%d]", i );
1465 check_hidp_button_caps( &button_caps[i], &expect_button_caps[i] );
1466 winetest_pop_context();
1469 count = ARRAY_SIZE(button_caps) - 1;
1470 status = HidP_GetSpecificButtonCaps( HidP_Output, 0, 0, 0, button_caps, &count, preparsed_data );
1471 ok( status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetSpecificButtonCaps returned %#x\n", status );
1472 status = HidP_GetSpecificButtonCaps( HidP_Feature + 1, 0, 0, 0, button_caps, &count, preparsed_data );
1473 ok( status == HIDP_STATUS_INVALID_REPORT_TYPE, "HidP_GetSpecificButtonCaps returned %#x\n", status );
1474 count = 0;
1475 status = HidP_GetSpecificButtonCaps( HidP_Input, 0, 0, 0, button_caps, &count, preparsed_data );
1476 ok( status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_GetSpecificButtonCaps returned %#x\n", status );
1477 ok( count == caps.NumberInputButtonCaps, "HidP_GetSpecificButtonCaps returned count %d, expected %d\n",
1478 count, caps.NumberInputButtonCaps );
1479 count = ARRAY_SIZE(button_caps) - 1;
1480 status = HidP_GetSpecificButtonCaps( HidP_Input, 0, 0, 0, button_caps, &count, (PHIDP_PREPARSED_DATA)buffer );
1481 ok( status == HIDP_STATUS_INVALID_PREPARSED_DATA, "HidP_GetSpecificButtonCaps returned %#x\n", status );
1483 status = HidP_GetSpecificButtonCaps( HidP_Input, 0, 0, 0, button_caps + 1, &count, preparsed_data );
1484 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetSpecificButtonCaps returned %#x\n", status );
1485 ok( count == caps.NumberInputButtonCaps, "HidP_GetSpecificButtonCaps returned count %d, expected %d\n",
1486 count, caps.NumberInputButtonCaps );
1487 check_hidp_button_caps( &button_caps[1], &button_caps[0] );
1489 status = HidP_GetSpecificButtonCaps( HidP_Input, HID_USAGE_PAGE_BUTTON, 0, 5, button_caps + 1,
1490 &count, preparsed_data );
1491 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetSpecificButtonCaps returned %#x\n", status );
1492 ok( count == 1, "HidP_GetSpecificButtonCaps returned count %d, expected %d\n", count, 1 );
1493 check_hidp_button_caps( &button_caps[1], &button_caps[0] );
1495 count = 0xbeef;
1496 status = HidP_GetSpecificButtonCaps( HidP_Input, 0xfffe, 0, 0, button_caps, &count, preparsed_data );
1497 ok( status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetSpecificButtonCaps returned %#x\n", status );
1498 ok( count == 0, "HidP_GetSpecificButtonCaps returned count %d, expected %d\n", count, 0 );
1499 count = 0xbeef;
1500 status = HidP_GetSpecificButtonCaps( HidP_Input, 0, 0xfffe, 0, button_caps, &count, preparsed_data );
1501 ok( status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetSpecificButtonCaps returned %#x\n", status );
1502 ok( count == 0, "HidP_GetSpecificButtonCaps returned count %d, expected %d\n", count, 0 );
1503 count = 0xbeef;
1504 status = HidP_GetSpecificButtonCaps( HidP_Input, 0, 0, 0xfffe, button_caps, &count, preparsed_data );
1505 ok( status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetSpecificButtonCaps returned %#x\n", status );
1506 ok( count == 0, "HidP_GetSpecificButtonCaps returned count %d, expected %d\n", count, 0 );
1508 count = ARRAY_SIZE(value_caps);
1509 status = HidP_GetValueCaps( HidP_Output, value_caps, &count, preparsed_data );
1510 ok( status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetValueCaps returned %#x\n", status );
1511 status = HidP_GetValueCaps( HidP_Feature + 1, value_caps, &count, preparsed_data );
1512 ok( status == HIDP_STATUS_INVALID_REPORT_TYPE, "HidP_GetValueCaps returned %#x\n", status );
1513 count = 0;
1514 status = HidP_GetValueCaps( HidP_Input, value_caps, &count, preparsed_data );
1515 ok( status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_GetValueCaps returned %#x\n", status );
1516 ok( count == caps.NumberInputValueCaps, "HidP_GetValueCaps returned count %d, expected %d\n",
1517 count, caps.NumberInputValueCaps );
1518 count = ARRAY_SIZE(value_caps);
1519 status = HidP_GetValueCaps( HidP_Input, value_caps, &count, (PHIDP_PREPARSED_DATA)buffer );
1520 ok( status == HIDP_STATUS_INVALID_PREPARSED_DATA, "HidP_GetValueCaps returned %#x\n", status );
1521 status = HidP_GetValueCaps( HidP_Input, value_caps, &count, preparsed_data );
1522 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetValueCaps returned %#x\n", status );
1523 ok( count == caps.NumberInputValueCaps, "HidP_GetValueCaps returned count %d, expected %d\n",
1524 count, caps.NumberInputValueCaps );
1526 for (i = 0; i < ARRAY_SIZE(expect_value_caps); ++i)
1528 winetest_push_context( "value_caps[%d]", i );
1529 check_hidp_value_caps( &value_caps[i], &expect_value_caps[i] );
1530 winetest_pop_context();
1533 count = ARRAY_SIZE(value_caps) - 4;
1534 status = HidP_GetSpecificValueCaps( HidP_Output, 0, 0, 0, value_caps, &count, preparsed_data );
1535 ok( status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetSpecificValueCaps returned %#x\n", status );
1536 status = HidP_GetSpecificValueCaps( HidP_Feature + 1, 0, 0, 0, value_caps, &count, preparsed_data );
1537 ok( status == HIDP_STATUS_INVALID_REPORT_TYPE, "HidP_GetSpecificValueCaps returned %#x\n", status );
1538 count = 0;
1539 status = HidP_GetSpecificValueCaps( HidP_Input, 0, 0, 0, value_caps, &count, preparsed_data );
1540 ok( status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_GetSpecificValueCaps returned %#x\n", status );
1541 ok( count == caps.NumberInputValueCaps, "HidP_GetSpecificValueCaps returned count %d, expected %d\n",
1542 count, caps.NumberInputValueCaps );
1543 count = ARRAY_SIZE(value_caps) - 4;
1544 status = HidP_GetSpecificValueCaps( HidP_Input, 0, 0, 0, value_caps + 4, &count, (PHIDP_PREPARSED_DATA)buffer );
1545 ok( status == HIDP_STATUS_INVALID_PREPARSED_DATA, "HidP_GetSpecificValueCaps returned %#x\n", status );
1547 status = HidP_GetSpecificValueCaps( HidP_Input, 0, 0, 0, value_caps + 4, &count, preparsed_data );
1548 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetSpecificValueCaps returned %#x\n", status );
1549 ok( count == caps.NumberInputValueCaps, "HidP_GetSpecificValueCaps returned count %d, expected %d\n",
1550 count, caps.NumberInputValueCaps );
1551 check_hidp_value_caps( &value_caps[4], &value_caps[0] );
1552 check_hidp_value_caps( &value_caps[5], &value_caps[1] );
1553 check_hidp_value_caps( &value_caps[6], &value_caps[2] );
1554 check_hidp_value_caps( &value_caps[7], &value_caps[3] );
1556 count = 1;
1557 status = HidP_GetSpecificValueCaps( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_HATSWITCH,
1558 value_caps + 4, &count, preparsed_data );
1559 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetSpecificValueCaps returned %#x\n", status );
1560 ok( count == 1, "HidP_GetSpecificValueCaps returned count %d, expected %d\n", count, 1 );
1561 check_hidp_value_caps( &value_caps[4], &value_caps[3] );
1563 count = 0xdead;
1564 status = HidP_GetSpecificValueCaps( HidP_Input, 0xfffe, 0, 0, value_caps, &count, preparsed_data );
1565 ok( status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetSpecificValueCaps returned %#x\n", status );
1566 ok( count == 0, "HidP_GetSpecificValueCaps returned count %d, expected %d\n", count, 0 );
1567 count = 0xdead;
1568 status = HidP_GetSpecificValueCaps( HidP_Input, 0, 0xfffe, 0, value_caps, &count, preparsed_data );
1569 ok( status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetSpecificValueCaps returned %#x\n", status );
1570 ok( count == 0, "HidP_GetSpecificValueCaps returned count %d, expected %d\n", count, 0 );
1571 count = 0xdead;
1572 status = HidP_GetSpecificValueCaps( HidP_Input, 0, 0, 0xfffe, value_caps, &count, preparsed_data );
1573 ok( status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetSpecificValueCaps returned %#x\n", status );
1574 ok( count == 0, "HidP_GetSpecificValueCaps returned count %d, expected %d\n", count, 0 );
1576 status = HidP_InitializeReportForID( HidP_Input, 0, (PHIDP_PREPARSED_DATA)buffer, report, sizeof(report) );
1577 ok( status == HIDP_STATUS_INVALID_PREPARSED_DATA, "HidP_InitializeReportForID returned %#x\n", status );
1578 status = HidP_InitializeReportForID( HidP_Feature + 1, 0, preparsed_data, report, sizeof(report) );
1579 ok( status == HIDP_STATUS_INVALID_REPORT_TYPE, "HidP_InitializeReportForID returned %#x\n", status );
1580 status = HidP_InitializeReportForID( HidP_Input, 0, preparsed_data, report, sizeof(report) );
1581 ok( status == HIDP_STATUS_INVALID_REPORT_LENGTH, "HidP_InitializeReportForID returned %#x\n", status );
1582 status = HidP_InitializeReportForID( HidP_Input, 0, preparsed_data, report, caps.InputReportByteLength + 1 );
1583 ok( status == HIDP_STATUS_INVALID_REPORT_LENGTH, "HidP_InitializeReportForID returned %#x\n", status );
1584 status = HidP_InitializeReportForID( HidP_Input, 1 - report_id, preparsed_data, report,
1585 caps.InputReportByteLength );
1586 ok( status == HIDP_STATUS_REPORT_DOES_NOT_EXIST, "HidP_InitializeReportForID returned %#x\n", status );
1588 memset( report, 0xcd, sizeof(report) );
1589 status = HidP_InitializeReportForID( HidP_Input, report_id, preparsed_data, report, caps.InputReportByteLength );
1590 ok( status == HIDP_STATUS_SUCCESS, "HidP_InitializeReportForID returned %#x\n", status );
1592 memset( buffer, 0xcd, sizeof(buffer) );
1593 memset( buffer, 0, caps.InputReportByteLength );
1594 buffer[0] = report_id;
1595 ok( !memcmp( buffer, report, sizeof(buffer) ), "unexpected report data\n" );
1597 status = HidP_SetUsageValueArray( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_X, buffer,
1598 sizeof(buffer), preparsed_data, report, caps.InputReportByteLength );
1599 ok( status == HIDP_STATUS_NOT_VALUE_ARRAY, "HidP_SetUsageValueArray returned %#x\n", status );
1600 memset( buffer, 0xcd, sizeof(buffer) );
1601 status = HidP_SetUsageValueArray( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_HATSWITCH,
1602 buffer, 0, preparsed_data, report, caps.InputReportByteLength );
1603 ok( status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_SetUsageValueArray returned %#x\n", status );
1604 status = HidP_SetUsageValueArray( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_HATSWITCH,
1605 buffer, 8, preparsed_data, report, caps.InputReportByteLength );
1606 todo_wine
1607 ok( status == HIDP_STATUS_NOT_IMPLEMENTED, "HidP_SetUsageValueArray returned %#x\n", status );
1609 status = HidP_GetUsageValueArray( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_X, buffer,
1610 sizeof(buffer), preparsed_data, report, caps.InputReportByteLength );
1611 ok( status == HIDP_STATUS_NOT_VALUE_ARRAY, "HidP_GetUsageValueArray returned %#x\n", status );
1612 memset( buffer, 0xcd, sizeof(buffer) );
1613 status = HidP_GetUsageValueArray( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_HATSWITCH,
1614 buffer, 0, preparsed_data, report, caps.InputReportByteLength );
1615 ok( status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_GetUsageValueArray returned %#x\n", status );
1616 status = HidP_GetUsageValueArray( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_HATSWITCH,
1617 buffer, 8, preparsed_data, report, caps.InputReportByteLength );
1618 todo_wine
1619 ok( status == HIDP_STATUS_NOT_IMPLEMENTED, "HidP_GetUsageValueArray returned %#x\n", status );
1621 value = -128;
1622 status = HidP_SetUsageValue( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_X, value,
1623 preparsed_data, report, caps.InputReportByteLength );
1624 ok( status == HIDP_STATUS_SUCCESS, "HidP_SetUsageValue returned %#x\n", status );
1625 value = 0xdeadbeef;
1626 status = HidP_GetUsageValue( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_X, &value,
1627 preparsed_data, report, caps.InputReportByteLength );
1628 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetUsageValue returned %#x\n", status );
1629 ok( value == 0x80, "got value %x, expected %#x\n", value, 0x80 );
1630 value = 0xdeadbeef;
1631 status = HidP_GetScaledUsageValue( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_X,
1632 (LONG *)&value, preparsed_data, report, caps.InputReportByteLength );
1633 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetScaledUsageValue returned %#x\n", status );
1634 ok( value == -128, "got value %x, expected %#x\n", value, -128 );
1636 value = 127;
1637 status = HidP_SetUsageValue( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_X, value,
1638 preparsed_data, report, caps.InputReportByteLength );
1639 ok( status == HIDP_STATUS_SUCCESS, "HidP_SetUsageValue returned %#x\n", status );
1640 value = 0xdeadbeef;
1641 status = HidP_GetScaledUsageValue( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_X,
1642 (LONG *)&value, preparsed_data, report, caps.InputReportByteLength );
1643 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetScaledUsageValue returned %#x\n", status );
1644 ok( value == 127, "got value %x, expected %#x\n", value, 127 );
1646 value = 0;
1647 status = HidP_SetUsageValue( 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_SetUsageValue returned %#x\n", status );
1650 value = 0xdeadbeef;
1651 status = HidP_GetScaledUsageValue( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_X,
1652 (LONG *)&value, preparsed_data, report, caps.InputReportByteLength );
1653 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetScaledUsageValue returned %#x\n", status );
1654 ok( value == 0, "got value %x, expected %#x\n", value, 0 );
1656 value = 0x7fffffff;
1657 status = HidP_SetUsageValue( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z, value,
1658 preparsed_data, report, caps.InputReportByteLength );
1659 ok( status == HIDP_STATUS_SUCCESS, "HidP_SetUsageValue returned %#x\n", status );
1660 value = 0xdeadbeef;
1661 status = HidP_GetScaledUsageValue( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
1662 (LONG *)&value, preparsed_data, report, caps.InputReportByteLength );
1663 ok( status == HIDP_STATUS_VALUE_OUT_OF_RANGE, "HidP_GetScaledUsageValue returned %#x\n", status );
1664 ok( value == 0, "got value %x, expected %#x\n", value, 0 );
1665 value = 0xdeadbeef;
1666 status = HidP_GetUsageValue( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z, &value,
1667 preparsed_data, report, caps.InputReportByteLength );
1668 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetUsageValue returned %#x\n", status );
1669 ok( value == 0x7fffffff, "got value %x, expected %#x\n", value, 0x7fffffff );
1671 value = 0x3fffffff;
1672 status = HidP_SetUsageValue( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z, value,
1673 preparsed_data, report, caps.InputReportByteLength );
1674 ok( status == HIDP_STATUS_SUCCESS, "HidP_SetUsageValue returned %#x\n", status );
1675 value = 0xdeadbeef;
1676 status = HidP_GetScaledUsageValue( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
1677 (LONG *)&value, preparsed_data, report, caps.InputReportByteLength );
1678 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetScaledUsageValue returned %#x\n", status );
1679 ok( value == 0x7fffffff, "got value %x, expected %#x\n", value, 0x7fffffff );
1681 value = 0;
1682 status = HidP_SetUsageValue( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z, value,
1683 preparsed_data, report, caps.InputReportByteLength );
1684 ok( status == HIDP_STATUS_SUCCESS, "HidP_SetUsageValue returned %#x\n", status );
1685 value = 0xdeadbeef;
1686 status = HidP_GetScaledUsageValue( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
1687 (LONG *)&value, preparsed_data, report, caps.InputReportByteLength );
1688 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetScaledUsageValue returned %#x\n", status );
1689 ok( value == 0x80000000, "got value %x, expected %#x\n", value, 0x80000000 );
1691 value = 0;
1692 status = HidP_SetUsageValue( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_RX, value,
1693 preparsed_data, report, caps.InputReportByteLength );
1694 ok( status == HIDP_STATUS_SUCCESS, "HidP_SetUsageValue returned %#x\n", status );
1695 value = 0xdeadbeef;
1696 status = HidP_GetScaledUsageValue( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_RX,
1697 (LONG *)&value, preparsed_data, report, caps.InputReportByteLength );
1698 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetScaledUsageValue returned %#x\n", status );
1699 ok( value == 0, "got value %x, expected %#x\n", value, 0 );
1701 value = 0xfeedcafe;
1702 status = HidP_SetUsageValue( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_RY, value,
1703 preparsed_data, report, caps.InputReportByteLength );
1704 ok( status == HIDP_STATUS_SUCCESS, "HidP_SetUsageValue returned %#x\n", status );
1705 value = 0xdeadbeef;
1706 status = HidP_GetScaledUsageValue( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_RY,
1707 (LONG *)&value, preparsed_data, report, caps.InputReportByteLength );
1708 ok( status == HIDP_STATUS_BAD_LOG_PHY_VALUES, "HidP_GetScaledUsageValue returned %#x\n", status );
1709 ok( value == 0, "got value %x, expected %#x\n", value, 0 );
1710 status = HidP_SetScaledUsageValue( HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_RY,
1711 0, preparsed_data, report, caps.InputReportByteLength );
1712 ok( status == HIDP_STATUS_BAD_LOG_PHY_VALUES, "HidP_GetScaledUsageValue returned %#x\n", status );
1713 ok( value == 0, "got value %x, expected %#x\n", value, 0 );
1715 value = HidP_MaxUsageListLength( HidP_Feature + 1, 0, preparsed_data );
1716 ok( value == 0, "HidP_MaxUsageListLength(HidP_Feature + 1, 0) returned %d, expected %d\n", value, 0 );
1717 value = HidP_MaxUsageListLength( HidP_Input, 0, preparsed_data );
1718 ok( value == 50, "HidP_MaxUsageListLength(HidP_Input, 0) returned %d, expected %d\n", value, 50 );
1719 value = HidP_MaxUsageListLength( HidP_Input, HID_USAGE_PAGE_BUTTON, preparsed_data );
1720 ok( value == 32, "HidP_MaxUsageListLength(HidP_Input, HID_USAGE_PAGE_BUTTON) returned %d, expected %d\n",
1721 value, 32 );
1722 value = HidP_MaxUsageListLength( HidP_Input, HID_USAGE_PAGE_LED, preparsed_data );
1723 ok( value == 8, "HidP_MaxUsageListLength(HidP_Input, HID_USAGE_PAGE_LED) returned %d, expected %d\n",
1724 value, 8 );
1725 value = HidP_MaxUsageListLength( HidP_Feature, HID_USAGE_PAGE_BUTTON, preparsed_data );
1726 ok( value == 8, "HidP_MaxUsageListLength(HidP_Feature, HID_USAGE_PAGE_BUTTON) returned %d, expected %d\n",
1727 value, 8 );
1728 value = HidP_MaxUsageListLength( HidP_Feature, HID_USAGE_PAGE_LED, preparsed_data );
1729 ok( value == 0, "HidP_MaxUsageListLength(HidP_Feature, HID_USAGE_PAGE_LED) returned %d, expected %d\n",
1730 value, 0 );
1732 usages[0] = 0xff;
1733 value = 1;
1734 status = HidP_SetUsages( HidP_Input, HID_USAGE_PAGE_BUTTON, 0, usages, &value, preparsed_data,
1735 report, caps.InputReportByteLength );
1736 ok( status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_SetUsages returned %#x\n", status );
1737 usages[1] = 2;
1738 usages[2] = 0xff;
1739 value = 3;
1740 status = HidP_SetUsages( HidP_Input, HID_USAGE_PAGE_BUTTON, 0, usages, &value, preparsed_data,
1741 report, caps.InputReportByteLength );
1742 ok( status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_SetUsages returned %#x\n", status );
1743 usages[0] = 4;
1744 usages[1] = 6;
1745 value = 2;
1746 status = HidP_SetUsages( HidP_Input, HID_USAGE_PAGE_BUTTON, 0, usages, &value, preparsed_data,
1747 report, caps.InputReportByteLength );
1748 ok( status == HIDP_STATUS_SUCCESS, "HidP_SetUsages returned %#x\n", status );
1749 usages[0] = 4;
1750 usages[1] = 6;
1751 value = 2;
1752 status = HidP_SetUsages( HidP_Input, HID_USAGE_PAGE_LED, 0, usages, &value, preparsed_data,
1753 report, caps.InputReportByteLength );
1754 ok( status == HIDP_STATUS_SUCCESS, "HidP_SetUsages returned %#x\n", status );
1756 value = ARRAY_SIZE(usages);
1757 status = HidP_GetUsages( HidP_Input, HID_USAGE_PAGE_KEYBOARD, 0, usages, &value, preparsed_data,
1758 report, caps.InputReportByteLength );
1759 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetUsages returned %#x\n", status );
1760 ok( value == 0, "got usage count %d, expected %d\n", value, 2 );
1762 usages[0] = 0x9;
1763 usages[1] = 0xb;
1764 usages[2] = 0xa;
1765 value = 3;
1766 ok( report[6] == 0, "got report[6] %x expected 0\n", report[6] );
1767 ok( report[7] == 0, "got report[7] %x expected 0\n", report[7] );
1768 memcpy( buffer, report, caps.InputReportByteLength );
1769 status = HidP_SetUsages( HidP_Input, HID_USAGE_PAGE_KEYBOARD, 0, usages, &value, preparsed_data,
1770 report, caps.InputReportByteLength );
1771 ok( status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_SetUsages returned %#x\n", status );
1772 buffer[6] = 2;
1773 buffer[7] = 4;
1774 ok( !memcmp( buffer, report, caps.InputReportByteLength ), "unexpected report data\n" );
1776 status = HidP_SetUsageValue( HidP_Input, HID_USAGE_PAGE_LED, 0, 6, 1, preparsed_data, report,
1777 caps.InputReportByteLength );
1778 ok( status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_SetUsageValue returned %#x\n", status );
1780 value = 0xdeadbeef;
1781 status = HidP_GetUsageValue( HidP_Input, HID_USAGE_PAGE_LED, 0, 6, &value, preparsed_data,
1782 report, caps.InputReportByteLength );
1783 ok( status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_SetUsageValue returned %#x\n", status );
1784 ok( value == 0xdeadbeef, "got value %x, expected %#x\n", value, 0xdeadbeef );
1786 value = 1;
1787 status = HidP_GetUsages( HidP_Input, HID_USAGE_PAGE_BUTTON, 0, usages, &value, preparsed_data,
1788 report, caps.InputReportByteLength );
1789 ok( status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_GetUsages returned %#x\n", status );
1790 ok( value == 2, "got usage count %d, expected %d\n", value, 2 );
1791 value = ARRAY_SIZE(usages);
1792 memset( usages, 0xcd, sizeof(usages) );
1793 status = HidP_GetUsages( HidP_Input, HID_USAGE_PAGE_BUTTON, 0, usages, &value, preparsed_data,
1794 report, caps.InputReportByteLength );
1795 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetUsages returned %#x\n", status );
1796 ok( value == 2, "got usage count %d, expected %d\n", value, 2 );
1797 ok( usages[0] == 4, "got usages[0] %x, expected %x\n", usages[0], 4 );
1798 ok( usages[1] == 6, "got usages[1] %x, expected %x\n", usages[1], 6 );
1800 value = ARRAY_SIZE(usages);
1801 memset( usages, 0xcd, sizeof(usages) );
1802 status = HidP_GetUsages( HidP_Input, HID_USAGE_PAGE_LED, 0, usages, &value, preparsed_data,
1803 report, caps.InputReportByteLength );
1804 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetUsages returned %#x\n", status );
1805 ok( value == 2, "got usage count %d, expected %d\n", value, 2 );
1806 ok( usages[0] == 6, "got usages[0] %x, expected %x\n", usages[0], 6 );
1807 ok( usages[1] == 4, "got usages[1] %x, expected %x\n", usages[1], 4 );
1809 value = ARRAY_SIZE(usage_and_pages);
1810 memset( usage_and_pages, 0xcd, sizeof(usage_and_pages) );
1811 status = HidP_GetUsagesEx( HidP_Input, 0, usage_and_pages, &value, preparsed_data, report,
1812 caps.InputReportByteLength );
1813 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetUsagesEx returned %#x\n", status );
1814 ok( value == 6, "got usage count %d, expected %d\n", value, 4 );
1815 ok( usage_and_pages[0].UsagePage == HID_USAGE_PAGE_BUTTON, "got usage_and_pages[0] UsagePage %x, expected %x\n",
1816 usage_and_pages[0].UsagePage, HID_USAGE_PAGE_BUTTON );
1817 ok( usage_and_pages[1].UsagePage == HID_USAGE_PAGE_BUTTON, "got usage_and_pages[1] UsagePage %x, expected %x\n",
1818 usage_and_pages[1].UsagePage, HID_USAGE_PAGE_BUTTON );
1819 ok( usage_and_pages[2].UsagePage == HID_USAGE_PAGE_KEYBOARD, "got usage_and_pages[2] UsagePage %x, expected %x\n",
1820 usage_and_pages[2].UsagePage, HID_USAGE_PAGE_KEYBOARD );
1821 ok( usage_and_pages[3].UsagePage == HID_USAGE_PAGE_KEYBOARD, "got usage_and_pages[3] UsagePage %x, expected %x\n",
1822 usage_and_pages[3].UsagePage, HID_USAGE_PAGE_KEYBOARD );
1823 ok( usage_and_pages[4].UsagePage == HID_USAGE_PAGE_LED, "got usage_and_pages[4] UsagePage %x, expected %x\n",
1824 usage_and_pages[4].UsagePage, HID_USAGE_PAGE_LED );
1825 ok( usage_and_pages[5].UsagePage == HID_USAGE_PAGE_LED, "got usage_and_pages[5] UsagePage %x, expected %x\n",
1826 usage_and_pages[5].UsagePage, HID_USAGE_PAGE_LED );
1827 ok( usage_and_pages[0].Usage == 4, "got usage_and_pages[0] Usage %x, expected %x\n",
1828 usage_and_pages[0].Usage, 4 );
1829 ok( usage_and_pages[1].Usage == 6, "got usage_and_pages[1] Usage %x, expected %x\n",
1830 usage_and_pages[1].Usage, 6 );
1831 ok( usage_and_pages[2].Usage == 9, "got usage_and_pages[2] Usage %x, expected %x\n",
1832 usage_and_pages[2].Usage, 9 );
1833 ok( usage_and_pages[3].Usage == 11, "got usage_and_pages[3] Usage %x, expected %x\n",
1834 usage_and_pages[3].Usage, 11 );
1835 ok( usage_and_pages[4].Usage == 6, "got usage_and_pages[4] Usage %x, expected %x\n",
1836 usage_and_pages[4].Usage, 6 );
1837 ok( usage_and_pages[5].Usage == 4, "got usage_and_pages[5] Usage %x, expected %x\n",
1838 usage_and_pages[5].Usage, 4 );
1840 value = HidP_MaxDataListLength( HidP_Feature + 1, preparsed_data );
1841 ok( value == 0, "HidP_MaxDataListLength(HidP_Feature + 1) returned %d, expected %d\n", value, 0 );
1842 value = HidP_MaxDataListLength( HidP_Input, preparsed_data );
1843 ok( value == 58, "HidP_MaxDataListLength(HidP_Input) returned %d, expected %d\n", value, 58 );
1844 value = HidP_MaxDataListLength( HidP_Output, preparsed_data );
1845 ok( value == 0, "HidP_MaxDataListLength(HidP_Output) returned %d, expected %d\n", value, 0 );
1846 value = HidP_MaxDataListLength( HidP_Feature, preparsed_data );
1847 ok( value == 14, "HidP_MaxDataListLength(HidP_Feature) returned %d, expected %d\n", value, 14 );
1849 value = 1;
1850 status = HidP_GetData( HidP_Input, data, &value, preparsed_data, report, caps.InputReportByteLength );
1851 ok( status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_GetData returned %#x\n", status );
1852 ok( value == 11, "got data count %d, expected %d\n", value, 11 );
1853 memset( data, 0, sizeof(data) );
1854 status = HidP_GetData( HidP_Input, data, &value, preparsed_data, report, caps.InputReportByteLength );
1855 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetData returned %#x\n", status );
1856 for (i = 0; i < ARRAY_SIZE(expect_data); ++i)
1858 winetest_push_context( "data[%d]", i );
1859 check_member( data[i], expect_data[i], "%d", DataIndex );
1860 check_member( data[i], expect_data[i], "%d", RawValue );
1861 winetest_pop_context();
1864 /* HID nary usage collections are set with 1-based usage index in their declaration order */
1866 memset( report, 0, caps.InputReportByteLength );
1867 status = HidP_InitializeReportForID( HidP_Input, report_id, preparsed_data, report, caps.InputReportByteLength );
1868 ok( status == HIDP_STATUS_SUCCESS, "HidP_InitializeReportForID returned %#x\n", status );
1869 value = 2;
1870 usages[0] = 0x8e;
1871 usages[1] = 0x8f;
1872 status = HidP_SetUsages( HidP_Input, HID_USAGE_PAGE_KEYBOARD, 0, usages, &value, preparsed_data,
1873 report, caps.InputReportByteLength );
1874 ok( status == HIDP_STATUS_SUCCESS, "HidP_SetUsages returned %#x\n", status );
1875 ok( report[caps.InputReportByteLength - 2] == 3, "unexpected usage index %d, expected 3\n",
1876 report[caps.InputReportByteLength - 2] );
1877 ok( report[caps.InputReportByteLength - 1] == 4, "unexpected usage index %d, expected 4\n",
1878 report[caps.InputReportByteLength - 1] );
1879 status = HidP_UnsetUsages( HidP_Input, HID_USAGE_PAGE_KEYBOARD, 0, usages, &value,
1880 preparsed_data, report, caps.InputReportByteLength );
1881 ok( status == HIDP_STATUS_SUCCESS, "HidP_UnsetUsages returned %#x\n", status );
1882 ok( report[caps.InputReportByteLength - 2] == 0, "unexpected usage index %d, expected 0\n",
1883 report[caps.InputReportByteLength - 2] );
1884 ok( report[caps.InputReportByteLength - 1] == 0, "unexpected usage index %d, expected 0\n",
1885 report[caps.InputReportByteLength - 1] );
1886 status = HidP_UnsetUsages( HidP_Input, HID_USAGE_PAGE_KEYBOARD, 0, usages, &value,
1887 preparsed_data, report, caps.InputReportByteLength );
1888 ok( status == HIDP_STATUS_BUTTON_NOT_PRESSED, "HidP_UnsetUsages returned %#x\n", status );
1889 value = 1;
1890 usages[0] = 0x8c;
1891 status = HidP_SetUsages( HidP_Input, HID_USAGE_PAGE_KEYBOARD, 0, usages, &value, preparsed_data,
1892 report, caps.InputReportByteLength );
1893 ok( status == HIDP_STATUS_SUCCESS, "HidP_SetUsages returned %#x\n", status );
1894 ok( report[caps.InputReportByteLength - 2] == 1, "unexpected usage index %d, expected 1\n",
1895 report[caps.InputReportByteLength - 2] );
1897 memset( report, 0xcd, sizeof(report) );
1898 status = HidP_InitializeReportForID( HidP_Feature, 3, preparsed_data, report, caps.FeatureReportByteLength );
1899 ok( status == HIDP_STATUS_REPORT_DOES_NOT_EXIST, "HidP_InitializeReportForID returned %#x\n", status );
1901 memset( report, 0xcd, sizeof(report) );
1902 status = HidP_InitializeReportForID( HidP_Feature, report_id, preparsed_data, report,
1903 caps.FeatureReportByteLength );
1904 ok( status == HIDP_STATUS_SUCCESS, "HidP_InitializeReportForID returned %#x\n", status );
1906 memset( buffer, 0xcd, sizeof(buffer) );
1907 memset( buffer, 0, caps.FeatureReportByteLength );
1908 buffer[0] = report_id;
1909 ok( !memcmp( buffer, report, sizeof(buffer) ), "unexpected report data\n" );
1911 for (i = 0; i < caps.NumberLinkCollectionNodes; ++i)
1913 if (collections[i].LinkUsagePage != HID_USAGE_PAGE_HAPTICS) continue;
1914 if (collections[i].LinkUsage == HID_USAGE_HAPTICS_WAVEFORM_LIST) break;
1916 ok( i < caps.NumberLinkCollectionNodes,
1917 "HID_USAGE_HAPTICS_WAVEFORM_LIST collection not found\n" );
1918 waveform_list = i;
1920 status = HidP_SetUsageValue( HidP_Feature, HID_USAGE_PAGE_ORDINAL, waveform_list, 3,
1921 HID_USAGE_HAPTICS_WAVEFORM_RUMBLE, (PHIDP_PREPARSED_DATA)buffer,
1922 report, caps.FeatureReportByteLength );
1923 ok( status == HIDP_STATUS_INVALID_PREPARSED_DATA, "HidP_SetUsageValue returned %#x\n", status );
1924 status = HidP_SetUsageValue( HidP_Feature + 1, HID_USAGE_PAGE_ORDINAL, waveform_list, 3,
1925 HID_USAGE_HAPTICS_WAVEFORM_RUMBLE, preparsed_data, report,
1926 caps.FeatureReportByteLength );
1927 ok( status == HIDP_STATUS_INVALID_REPORT_TYPE, "HidP_SetUsageValue returned %#x\n", status );
1928 status = HidP_SetUsageValue( HidP_Feature, HID_USAGE_PAGE_ORDINAL, waveform_list, 3,
1929 HID_USAGE_HAPTICS_WAVEFORM_RUMBLE, preparsed_data, report,
1930 caps.FeatureReportByteLength + 1 );
1931 ok( status == HIDP_STATUS_INVALID_REPORT_LENGTH, "HidP_SetUsageValue returned %#x\n", status );
1932 report[0] = 1 - report_id;
1933 status = HidP_SetUsageValue( HidP_Feature, HID_USAGE_PAGE_ORDINAL, waveform_list, 3,
1934 HID_USAGE_HAPTICS_WAVEFORM_RUMBLE, preparsed_data, report,
1935 caps.FeatureReportByteLength );
1936 ok( status == (report_id ? HIDP_STATUS_SUCCESS : HIDP_STATUS_INCOMPATIBLE_REPORT_ID),
1937 "HidP_SetUsageValue returned %#x\n", status );
1938 report[0] = 2;
1939 status = HidP_SetUsageValue( HidP_Feature, HID_USAGE_PAGE_ORDINAL, waveform_list, 3,
1940 HID_USAGE_HAPTICS_WAVEFORM_RUMBLE, preparsed_data, report,
1941 caps.FeatureReportByteLength );
1942 ok( status == HIDP_STATUS_INCOMPATIBLE_REPORT_ID, "HidP_SetUsageValue returned %#x\n", status );
1943 report[0] = report_id;
1944 status = HidP_SetUsageValue( HidP_Feature, HID_USAGE_PAGE_ORDINAL, 0xdead, 3, HID_USAGE_HAPTICS_WAVEFORM_RUMBLE,
1945 preparsed_data, report, caps.FeatureReportByteLength );
1946 ok( status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_SetUsageValue returned %#x\n", status );
1948 status = HidP_SetUsageValue( HidP_Feature, HID_USAGE_PAGE_ORDINAL, waveform_list, 3,
1949 HID_USAGE_HAPTICS_WAVEFORM_RUMBLE, preparsed_data, report,
1950 caps.FeatureReportByteLength );
1951 ok( status == HIDP_STATUS_SUCCESS, "HidP_SetUsageValue returned %#x\n", status );
1953 memset( buffer, 0xcd, sizeof(buffer) );
1954 memset( buffer, 0, caps.FeatureReportByteLength );
1955 buffer[0] = report_id;
1956 value = HID_USAGE_HAPTICS_WAVEFORM_RUMBLE;
1957 memcpy( buffer + 1, &value, 2 );
1958 ok( !memcmp( buffer, report, sizeof(buffer) ), "unexpected report data\n" );
1960 status = HidP_GetUsageValue( HidP_Feature, HID_USAGE_PAGE_ORDINAL, waveform_list, 3, &value,
1961 (PHIDP_PREPARSED_DATA)buffer, report, caps.FeatureReportByteLength );
1962 ok( status == HIDP_STATUS_INVALID_PREPARSED_DATA, "HidP_GetUsageValue returned %#x\n", status );
1963 status = HidP_GetUsageValue( HidP_Feature + 1, HID_USAGE_PAGE_ORDINAL, waveform_list, 3, &value,
1964 preparsed_data, report, caps.FeatureReportByteLength );
1965 ok( status == HIDP_STATUS_INVALID_REPORT_TYPE, "HidP_GetUsageValue returned %#x\n", status );
1966 status = HidP_GetUsageValue( HidP_Feature, HID_USAGE_PAGE_ORDINAL, waveform_list, 3, &value,
1967 preparsed_data, report, caps.FeatureReportByteLength + 1 );
1968 ok( status == HIDP_STATUS_INVALID_REPORT_LENGTH, "HidP_GetUsageValue returned %#x\n", status );
1969 report[0] = 1 - report_id;
1970 status = HidP_GetUsageValue( HidP_Feature, HID_USAGE_PAGE_ORDINAL, waveform_list, 3, &value,
1971 preparsed_data, report, caps.FeatureReportByteLength );
1972 ok( status == (report_id ? HIDP_STATUS_SUCCESS : HIDP_STATUS_INCOMPATIBLE_REPORT_ID),
1973 "HidP_GetUsageValue returned %#x\n", status );
1974 report[0] = 2;
1975 status = HidP_GetUsageValue( HidP_Feature, HID_USAGE_PAGE_ORDINAL, waveform_list, 3, &value,
1976 preparsed_data, report, caps.FeatureReportByteLength );
1977 ok( status == HIDP_STATUS_INCOMPATIBLE_REPORT_ID, "HidP_GetUsageValue returned %#x\n", status );
1978 report[0] = report_id;
1979 status = HidP_GetUsageValue( HidP_Feature, HID_USAGE_PAGE_ORDINAL, 0xdead, 3, &value,
1980 preparsed_data, report, caps.FeatureReportByteLength );
1981 ok( status == HIDP_STATUS_USAGE_NOT_FOUND, "HidP_GetUsageValue returned %#x\n", status );
1983 value = 0xdeadbeef;
1984 status = HidP_GetUsageValue( HidP_Feature, HID_USAGE_PAGE_ORDINAL, waveform_list, 3, &value,
1985 preparsed_data, report, caps.FeatureReportByteLength );
1986 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetUsageValue returned %#x\n", status );
1987 ok( value == HID_USAGE_HAPTICS_WAVEFORM_RUMBLE, "got value %x, expected %#x\n", value,
1988 HID_USAGE_HAPTICS_WAVEFORM_RUMBLE );
1990 memset( buffer, 0xff, sizeof(buffer) );
1991 status = HidP_SetUsageValueArray( HidP_Feature, HID_USAGE_PAGE_HAPTICS, 0,
1992 HID_USAGE_HAPTICS_WAVEFORM_CUTOFF_TIME, buffer, 0,
1993 preparsed_data, report, caps.FeatureReportByteLength );
1994 ok( status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_SetUsageValueArray returned %#x\n", status );
1995 status = HidP_SetUsageValueArray( HidP_Feature, HID_USAGE_PAGE_HAPTICS, 0,
1996 HID_USAGE_HAPTICS_WAVEFORM_CUTOFF_TIME, buffer, 64,
1997 preparsed_data, report, caps.FeatureReportByteLength );
1998 ok( status == HIDP_STATUS_SUCCESS, "HidP_SetUsageValueArray returned %#x\n", status );
1999 ok( !memcmp( report + 9, buffer, 8 ), "unexpected report data\n" );
2001 memset( buffer, 0, sizeof(buffer) );
2002 status = HidP_GetUsageValueArray( HidP_Feature, HID_USAGE_PAGE_HAPTICS, 0,
2003 HID_USAGE_HAPTICS_WAVEFORM_CUTOFF_TIME, buffer, 0,
2004 preparsed_data, report, caps.FeatureReportByteLength );
2005 ok( status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_GetUsageValueArray returned %#x\n", status );
2006 status = HidP_GetUsageValueArray( HidP_Feature, HID_USAGE_PAGE_HAPTICS, 0,
2007 HID_USAGE_HAPTICS_WAVEFORM_CUTOFF_TIME, buffer, 64,
2008 preparsed_data, report, caps.FeatureReportByteLength );
2009 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetUsageValueArray returned %#x\n", status );
2010 memset( buffer + 16, 0xff, 8 );
2011 ok( !memcmp( buffer, buffer + 16, 16 ), "unexpected report value\n" );
2013 value = 0x7fffffff;
2014 status = HidP_SetUsageValue( HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
2015 value, preparsed_data, report, caps.FeatureReportByteLength );
2016 ok( status == HIDP_STATUS_SUCCESS, "HidP_SetUsageValue returned %#x\n", status );
2017 value = 0xdeadbeef;
2018 status = HidP_GetScaledUsageValue( HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
2019 (LONG *)&value, preparsed_data, report, caps.FeatureReportByteLength );
2020 ok( status == HIDP_STATUS_VALUE_OUT_OF_RANGE, "HidP_GetScaledUsageValue returned %#x\n", status );
2021 ok( value == 0, "got value %x, expected %#x\n", value, 0 );
2022 value = 0xdeadbeef;
2023 status = HidP_GetUsageValue( HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
2024 &value, preparsed_data, report, caps.FeatureReportByteLength );
2025 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetUsageValue returned %#x\n", status );
2026 ok( value == 0x7fffffff, "got value %x, expected %#x\n", value, 0x7fffffff );
2028 value = 0x7fff;
2029 status = HidP_SetUsageValue( HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
2030 value, preparsed_data, report, caps.FeatureReportByteLength );
2031 ok( status == HIDP_STATUS_SUCCESS, "HidP_SetUsageValue returned %#x\n", status );
2032 value = 0xdeadbeef;
2033 status = HidP_GetScaledUsageValue( HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
2034 (LONG *)&value, preparsed_data, report, caps.FeatureReportByteLength );
2035 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetScaledUsageValue returned %#x\n", status );
2036 ok( value == 0x0003ffff, "got value %x, expected %#x\n", value, 0x0003ffff );
2038 value = 0;
2039 status = HidP_SetUsageValue( HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
2040 value, preparsed_data, report, caps.FeatureReportByteLength );
2041 ok( status == HIDP_STATUS_SUCCESS, "HidP_SetUsageValue returned %#x\n", status );
2042 value = 0xdeadbeef;
2043 status = HidP_GetScaledUsageValue( HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
2044 (LONG *)&value, preparsed_data, report, caps.FeatureReportByteLength );
2045 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetScaledUsageValue returned %#x\n", status );
2046 ok( value == 0xfff90000, "got value %x, expected %#x\n", value, 0xfff90000 );
2047 status = HidP_SetScaledUsageValue( HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
2048 0x1000, preparsed_data, report, caps.FeatureReportByteLength );
2049 ok( status == HIDP_STATUS_SUCCESS, "HidP_SetScaledUsageValue returned %#x\n", status );
2050 value = 0;
2051 status = HidP_GetUsageValue( HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
2052 &value, preparsed_data, report, caps.FeatureReportByteLength );
2053 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetUsageValue returned %#x\n", status );
2054 ok( value == 0xfffff518, "got value %x, expected %#x\n", value, 0xfffff518 );
2055 status = HidP_SetScaledUsageValue( HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
2056 0, preparsed_data, report, caps.FeatureReportByteLength );
2057 ok( status == HIDP_STATUS_SUCCESS, "HidP_SetScaledUsageValue returned %#x\n", status );
2058 value = 0;
2059 status = HidP_GetUsageValue( HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
2060 &value, preparsed_data, report, caps.FeatureReportByteLength );
2061 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetUsageValue returned %#x\n", status );
2062 ok( value == 0xfffff45e, "got value %x, expected %#x\n", value, 0xfffff45e );
2063 status = HidP_SetScaledUsageValue( HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
2064 0xdead, preparsed_data, report, caps.FeatureReportByteLength );
2065 ok( status == HIDP_STATUS_SUCCESS, "HidP_SetScaledUsageValue returned %#x\n", status );
2066 value = 0;
2067 status = HidP_GetUsageValue( HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
2068 &value, preparsed_data, report, caps.FeatureReportByteLength );
2069 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetUsageValue returned %#x\n", status );
2070 ok( value == 0xfffffe7d, "got value %x, expected %#x\n", value, 0xfffffe7d );
2071 status = HidP_SetScaledUsageValue( HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
2072 0xbeef, preparsed_data, report, caps.FeatureReportByteLength );
2073 ok( status == HIDP_STATUS_SUCCESS, "HidP_SetScaledUsageValue returned %#x\n", status );
2074 value = 0;
2075 status = HidP_GetUsageValue( HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
2076 &value, preparsed_data, report, caps.FeatureReportByteLength );
2077 ok( status == HIDP_STATUS_SUCCESS, "HidP_GetUsageValue returned %#x\n", status );
2078 ok( value == 0xfffffd0b, "got value %x, expected %#x\n", value, 0xfffffd0b );
2080 test_hidp_get_input( file, report_id, caps.InputReportByteLength, preparsed_data );
2081 test_hidp_get_feature( file, report_id, caps.FeatureReportByteLength, preparsed_data );
2082 test_hidp_set_feature( file, report_id, caps.FeatureReportByteLength, preparsed_data );
2083 test_hidp_set_output( file, report_id, caps.OutputReportByteLength, preparsed_data );
2084 test_write_file( file, report_id, caps.OutputReportByteLength );
2086 memset( report, 0xcd, sizeof(report) );
2087 SetLastError( 0xdeadbeef );
2088 ret = ReadFile( file, report, 0, &value, NULL );
2089 ok( !ret && GetLastError() == ERROR_INVALID_USER_BUFFER, "ReadFile failed, last error %u\n",
2090 GetLastError() );
2091 ok( value == 0, "ReadFile returned %x\n", value );
2092 SetLastError( 0xdeadbeef );
2093 ret = ReadFile( file, report, caps.InputReportByteLength - 1, &value, NULL );
2094 ok( !ret && GetLastError() == ERROR_INVALID_USER_BUFFER, "ReadFile failed, last error %u\n",
2095 GetLastError() );
2096 ok( value == 0, "ReadFile returned %x\n", value );
2098 if (polled)
2100 struct hid_expect expect[] =
2103 .code = IOCTL_HID_READ_REPORT,
2104 .report_len = caps.InputReportByteLength - (report_id ? 0 : 1),
2105 .report_buf = {report_id ? report_id : 0x5a,0x5a,0},
2106 .ret_length = 3,
2107 .ret_status = STATUS_SUCCESS,
2110 .code = IOCTL_HID_READ_REPORT,
2111 .report_len = caps.InputReportByteLength - (report_id ? 0 : 1),
2112 .report_buf = {report_id ? report_id : 0x5a,0x5a,1},
2113 .ret_length = 3,
2114 .ret_status = STATUS_SUCCESS,
2118 send_hid_input( file, expect, sizeof(expect) );
2120 memset( report, 0xcd, sizeof(report) );
2121 SetLastError( 0xdeadbeef );
2122 ret = ReadFile( file, report, caps.InputReportByteLength, &value, NULL );
2123 ok( ret, "ReadFile failed, last error %u\n", GetLastError() );
2124 ok( value == (report_id ? 3 : 4), "ReadFile returned %x\n", value );
2125 ok( report[0] == report_id, "unexpected report data\n" );
2127 overlapped.hEvent = CreateEventW( NULL, FALSE, FALSE, NULL );
2128 overlapped2.hEvent = CreateEventW( NULL, FALSE, FALSE, NULL );
2130 /* drain available input reports */
2131 SetLastError( 0xdeadbeef );
2132 while (ReadFile( async_file, report, caps.InputReportByteLength, NULL, &overlapped ))
2133 ResetEvent( overlapped.hEvent );
2134 ok( GetLastError() == ERROR_IO_PENDING, "ReadFile returned error %u\n", GetLastError() );
2135 ret = GetOverlappedResult( async_file, &overlapped, &value, TRUE );
2136 ok( ret, "GetOverlappedResult failed, last error %u\n", GetLastError() );
2137 ok( value == (report_id ? 3 : 4), "GetOverlappedResult returned length %u, expected %u\n",
2138 value, (report_id ? 3 : 4) );
2139 ResetEvent( overlapped.hEvent );
2141 memcpy( buffer, report, caps.InputReportByteLength );
2142 memcpy( buffer + caps.InputReportByteLength, report, caps.InputReportByteLength );
2144 SetLastError( 0xdeadbeef );
2145 ret = ReadFile( async_file, report, caps.InputReportByteLength, NULL, &overlapped );
2146 ok( !ret, "ReadFile succeeded\n" );
2147 ok( GetLastError() == ERROR_IO_PENDING, "ReadFile returned error %u\n", GetLastError() );
2149 SetLastError( 0xdeadbeef );
2150 ret = ReadFile( async_file, buffer, caps.InputReportByteLength, NULL, &overlapped2 );
2151 ok( !ret, "ReadFile succeeded\n" );
2152 ok( GetLastError() == ERROR_IO_PENDING, "ReadFile returned error %u\n", GetLastError() );
2154 /* wait for second report to be ready */
2155 ret = GetOverlappedResult( async_file, &overlapped2, &value, TRUE );
2156 ok( ret, "GetOverlappedResult failed, last error %u\n", GetLastError() );
2157 ok( value == (report_id ? 3 : 4), "GetOverlappedResult returned length %u, expected %u\n",
2158 value, (report_id ? 3 : 4) );
2159 /* first report should be ready and the same */
2160 ret = GetOverlappedResult( async_file, &overlapped, &value, FALSE );
2161 ok( ret, "GetOverlappedResult failed, last error %u\n", GetLastError() );
2162 ok( value == (report_id ? 3 : 4), "GetOverlappedResult returned length %u, expected %u\n",
2163 value, (report_id ? 3 : 4) );
2164 ok( memcmp( report, buffer + caps.InputReportByteLength, caps.InputReportByteLength ),
2165 "expected different report\n" );
2166 ok( !memcmp( report, buffer, caps.InputReportByteLength ), "expected identical reports\n" );
2168 CloseHandle( overlapped.hEvent );
2169 CloseHandle( overlapped2.hEvent );
2171 else
2173 struct hid_expect expect[] =
2176 .code = IOCTL_HID_READ_REPORT,
2177 .report_len = caps.InputReportByteLength - (report_id ? 0 : 1),
2178 .report_buf = {report_id ? report_id : 0x5a,0x5a,0x5a},
2179 .ret_length = 3,
2180 .ret_status = STATUS_SUCCESS,
2183 .code = IOCTL_HID_READ_REPORT,
2184 .report_len = caps.InputReportByteLength - (report_id ? 0 : 1),
2185 .report_buf = {report_id ? report_id : 0xa5,0xa5,0xa5,0xa5,0xa5},
2186 .ret_length = caps.InputReportByteLength - (report_id ? 0 : 1),
2187 .ret_status = STATUS_SUCCESS,
2191 overlapped.hEvent = CreateEventW( NULL, FALSE, FALSE, NULL );
2192 overlapped2.hEvent = CreateEventW( NULL, FALSE, FALSE, NULL );
2194 SetLastError( 0xdeadbeef );
2195 memset( report, 0, sizeof(report) );
2196 ret = ReadFile( async_file, report, caps.InputReportByteLength, NULL, &overlapped );
2197 ok( !ret, "ReadFile succeeded\n" );
2198 ok( GetLastError() == ERROR_IO_PENDING, "ReadFile returned error %u\n", GetLastError() );
2199 Sleep( 50 );
2200 ret = GetOverlappedResult( async_file, &overlapped, &value, FALSE );
2201 ok( !ret, "GetOverlappedResult succeeded\n" );
2202 ok( GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult returned error %u\n", GetLastError() );
2204 SetLastError( 0xdeadbeef );
2205 memset( buffer, 0, sizeof(buffer) );
2206 ret = ReadFile( async_file, buffer, caps.InputReportByteLength, NULL, &overlapped2 );
2207 ok( !ret, "ReadFile succeeded\n" );
2208 ok( GetLastError() == ERROR_IO_PENDING, "ReadFile returned error %u\n", GetLastError() );
2209 Sleep( 50 );
2210 ret = GetOverlappedResult( async_file, &overlapped2, &value, FALSE );
2211 ok( !ret, "GetOverlappedResult succeeded\n" );
2212 ok( GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult returned error %u\n", GetLastError() );
2214 memset( report + caps.InputReportByteLength, 0xa5, 5 );
2215 if (report_id) report[caps.InputReportByteLength] = report_id;
2217 send_hid_input( file, expect, sizeof(expect) );
2219 /* first read should be completed */
2220 ret = GetOverlappedResult( async_file, &overlapped, &value, TRUE );
2221 ok( ret, "GetOverlappedResult failed, last error %u\n", GetLastError() );
2222 ok( value == caps.InputReportByteLength, "got length %u, expected %u\n", value, caps.InputReportByteLength );
2223 /* second read should still be pending */
2224 Sleep( 50 );
2225 ret = GetOverlappedResult( async_file, &overlapped2, &value, FALSE );
2226 ok( !ret, "GetOverlappedResult succeeded\n" );
2227 ok( GetLastError() == ERROR_IO_INCOMPLETE, "GetOverlappedResult returned error %u\n", GetLastError() );
2229 memset( buffer + caps.InputReportByteLength, 0x3b, 5 );
2230 if (report_id) buffer[caps.InputReportByteLength] = report_id;
2231 memset( expect[1].report_buf, 0x3b, 5 );
2232 if (report_id) expect[1].report_buf[0] = report_id;
2234 send_hid_input( file, expect, sizeof(expect) );
2236 ret = GetOverlappedResult( async_file, &overlapped2, &value, TRUE );
2237 ok( ret, "GetOverlappedResult failed, last error %u\n", GetLastError() );
2238 ok( value == caps.InputReportByteLength, "got length %u, expected %u\n", value, caps.InputReportByteLength );
2240 off = report_id ? 0 : 1;
2241 ok( memcmp( report, buffer, caps.InputReportByteLength ), "expected different report\n" );
2242 ok( !memcmp( report + off, report + caps.InputReportByteLength, caps.InputReportByteLength - off ),
2243 "expected identical reports\n" );
2244 ok( !memcmp( buffer + off, buffer + caps.InputReportByteLength, caps.InputReportByteLength - off ),
2245 "expected identical reports\n" );
2247 CloseHandle( overlapped.hEvent );
2248 CloseHandle( overlapped2.hEvent );
2251 HidD_FreePreparsedData( preparsed_data );
2254 static void test_hid_device( DWORD report_id, DWORD polled, const HIDP_CAPS *expect_caps )
2256 char buffer[FIELD_OFFSET( SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath[MAX_PATH] )];
2257 SP_DEVICE_INTERFACE_DATA iface = {sizeof(SP_DEVICE_INTERFACE_DATA)};
2258 SP_DEVICE_INTERFACE_DETAIL_DATA_W *iface_detail = (void *)buffer;
2259 SP_DEVINFO_DATA device = {sizeof(SP_DEVINFO_DATA)};
2260 ULONG count, poll_freq, out_len;
2261 HANDLE file, async_file;
2262 BOOL ret, found = FALSE;
2263 OBJECT_ATTRIBUTES attr;
2264 UNICODE_STRING string;
2265 IO_STATUS_BLOCK io;
2266 NTSTATUS status;
2267 unsigned int i;
2268 HDEVINFO set;
2270 winetest_push_context( "id %d%s", report_id, polled ? " poll" : "" );
2272 set = SetupDiGetClassDevsW( &GUID_DEVINTERFACE_HID, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT );
2273 ok( set != INVALID_HANDLE_VALUE, "failed to get device list, error %#x\n", GetLastError() );
2275 for (i = 0; SetupDiEnumDeviceInfo( set, i, &device ); ++i)
2277 ret = SetupDiEnumDeviceInterfaces( set, &device, &GUID_DEVINTERFACE_HID, 0, &iface );
2278 ok( ret, "failed to get interface, error %#x\n", GetLastError() );
2279 ok( IsEqualGUID( &iface.InterfaceClassGuid, &GUID_DEVINTERFACE_HID ), "wrong class %s\n",
2280 debugstr_guid( &iface.InterfaceClassGuid ) );
2281 ok( iface.Flags == SPINT_ACTIVE, "got flags %#x\n", iface.Flags );
2283 iface_detail->cbSize = sizeof(*iface_detail);
2284 ret = SetupDiGetDeviceInterfaceDetailW( set, &iface, iface_detail, sizeof(buffer), NULL, NULL );
2285 ok( ret, "failed to get interface path, error %#x\n", GetLastError() );
2287 if (wcsstr( iface_detail->DevicePath, L"\\\\?\\hid#winetest#1" ))
2289 found = TRUE;
2290 break;
2294 SetupDiDestroyDeviceInfoList( set );
2296 todo_wine
2297 ok( found, "didn't find device\n" );
2299 file = CreateFileW( iface_detail->DevicePath, FILE_READ_ACCESS | FILE_WRITE_ACCESS,
2300 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
2301 ok( file != INVALID_HANDLE_VALUE, "got error %u\n", GetLastError() );
2303 count = 0xdeadbeef;
2304 SetLastError( 0xdeadbeef );
2305 ret = HidD_GetNumInputBuffers( file, &count );
2306 ok( ret, "HidD_GetNumInputBuffers failed last error %u\n", GetLastError() );
2307 ok( count == 32, "HidD_GetNumInputBuffers returned %u\n", count );
2309 SetLastError( 0xdeadbeef );
2310 ret = HidD_SetNumInputBuffers( file, 1 );
2311 ok( !ret, "HidD_SetNumInputBuffers succeeded\n" );
2312 ok( GetLastError() == ERROR_INVALID_PARAMETER, "HidD_SetNumInputBuffers returned error %u\n",
2313 GetLastError() );
2314 SetLastError( 0xdeadbeef );
2315 ret = HidD_SetNumInputBuffers( file, 513 );
2316 ok( !ret, "HidD_SetNumInputBuffers succeeded\n" );
2317 ok( GetLastError() == ERROR_INVALID_PARAMETER, "HidD_SetNumInputBuffers returned error %u\n",
2318 GetLastError() );
2320 SetLastError( 0xdeadbeef );
2321 ret = HidD_SetNumInputBuffers( file, 16 );
2322 ok( ret, "HidD_SetNumInputBuffers failed last error %u\n", GetLastError() );
2324 count = 0xdeadbeef;
2325 SetLastError( 0xdeadbeef );
2326 ret = HidD_GetNumInputBuffers( file, &count );
2327 ok( ret, "HidD_GetNumInputBuffers failed last error %u\n", GetLastError() );
2328 ok( count == 16, "HidD_GetNumInputBuffers returned %u\n", count );
2330 async_file = CreateFileW( iface_detail->DevicePath, FILE_READ_ACCESS | FILE_WRITE_ACCESS,
2331 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
2332 FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING, NULL );
2333 ok( async_file != INVALID_HANDLE_VALUE, "got error %u\n", GetLastError() );
2335 count = 0xdeadbeef;
2336 SetLastError( 0xdeadbeef );
2337 ret = HidD_GetNumInputBuffers( async_file, &count );
2338 ok( ret, "HidD_GetNumInputBuffers failed last error %u\n", GetLastError() );
2339 ok( count == 32, "HidD_GetNumInputBuffers returned %u\n", count );
2341 SetLastError( 0xdeadbeef );
2342 ret = HidD_SetNumInputBuffers( async_file, 2 );
2343 ok( ret, "HidD_SetNumInputBuffers failed last error %u\n", GetLastError() );
2345 count = 0xdeadbeef;
2346 SetLastError( 0xdeadbeef );
2347 ret = HidD_GetNumInputBuffers( async_file, &count );
2348 ok( ret, "HidD_GetNumInputBuffers failed last error %u\n", GetLastError() );
2349 ok( count == 2, "HidD_GetNumInputBuffers returned %u\n", count );
2350 count = 0xdeadbeef;
2351 SetLastError( 0xdeadbeef );
2352 ret = HidD_GetNumInputBuffers( file, &count );
2353 ok( ret, "HidD_GetNumInputBuffers failed last error %u\n", GetLastError() );
2354 ok( count == 16, "HidD_GetNumInputBuffers returned %u\n", count );
2356 if (polled)
2358 out_len = sizeof(ULONG);
2359 SetLastError( 0xdeadbeef );
2360 ret = sync_ioctl( file, IOCTL_HID_GET_POLL_FREQUENCY_MSEC, NULL, 0, &poll_freq, &out_len );
2361 ok( ret, "IOCTL_HID_GET_POLL_FREQUENCY_MSEC failed last error %u\n", GetLastError() );
2362 ok( out_len == sizeof(ULONG), "got out_len %u, expected sizeof(ULONG)\n", out_len );
2363 todo_wine
2364 ok( poll_freq == 5, "got poll_freq %u, expected 5\n", poll_freq );
2366 out_len = 0;
2367 poll_freq = 500;
2368 SetLastError( 0xdeadbeef );
2369 ret = sync_ioctl( file, IOCTL_HID_SET_POLL_FREQUENCY_MSEC, &poll_freq, sizeof(ULONG), NULL, &out_len );
2370 ok( ret, "IOCTL_HID_SET_POLL_FREQUENCY_MSEC failed last error %u\n", GetLastError() );
2371 ok( out_len == 0, "got out_len %u, expected 0\n", out_len );
2373 out_len = 0;
2374 poll_freq = 10001;
2375 SetLastError( 0xdeadbeef );
2376 ret = sync_ioctl( file, IOCTL_HID_SET_POLL_FREQUENCY_MSEC, &poll_freq, sizeof(ULONG), NULL, &out_len );
2377 ok( ret, "IOCTL_HID_SET_POLL_FREQUENCY_MSEC failed last error %u\n", GetLastError() );
2378 ok( out_len == 0, "got out_len %u, expected 0\n", out_len );
2380 out_len = 0;
2381 poll_freq = 0;
2382 SetLastError( 0xdeadbeef );
2383 ret = sync_ioctl( file, IOCTL_HID_SET_POLL_FREQUENCY_MSEC, &poll_freq, sizeof(ULONG), NULL, &out_len );
2384 ok( ret, "IOCTL_HID_SET_POLL_FREQUENCY_MSEC failed last error %u\n", GetLastError() );
2385 ok( out_len == 0, "got out_len %u, expected 0\n", out_len );
2387 out_len = sizeof(ULONG);
2388 SetLastError( 0xdeadbeef );
2389 ret = sync_ioctl( file, IOCTL_HID_GET_POLL_FREQUENCY_MSEC, NULL, 0, &poll_freq, &out_len );
2390 ok( ret, "IOCTL_HID_GET_POLL_FREQUENCY_MSEC failed last error %u\n", GetLastError() );
2391 ok( out_len == sizeof(ULONG), "got out_len %u, expected sizeof(ULONG)\n", out_len );
2392 ok( poll_freq == 10000, "got poll_freq %u, expected 10000\n", poll_freq );
2394 out_len = 0;
2395 poll_freq = 500;
2396 SetLastError( 0xdeadbeef );
2397 ret = sync_ioctl( file, IOCTL_HID_SET_POLL_FREQUENCY_MSEC, &poll_freq, sizeof(ULONG), NULL, &out_len );
2398 ok( ret, "IOCTL_HID_SET_POLL_FREQUENCY_MSEC failed last error %u\n", GetLastError() );
2399 ok( out_len == 0, "got out_len %u, expected 0\n", out_len );
2401 out_len = sizeof(ULONG);
2402 SetLastError( 0xdeadbeef );
2403 ret = sync_ioctl( async_file, IOCTL_HID_GET_POLL_FREQUENCY_MSEC, NULL, 0, &poll_freq, &out_len );
2404 ok( ret, "IOCTL_HID_GET_POLL_FREQUENCY_MSEC failed last error %u\n", GetLastError() );
2405 ok( out_len == sizeof(ULONG), "got out_len %u, expected sizeof(ULONG)\n", out_len );
2406 ok( poll_freq == 500, "got poll_freq %u, expected 500\n", poll_freq );
2409 test_hidp( file, async_file, report_id, polled, expect_caps );
2411 CloseHandle( async_file );
2412 CloseHandle( file );
2414 RtlInitUnicodeString( &string, L"\\??\\root#winetest#0#{deadbeef-29ef-4538-a5fd-b69573a362c0}" );
2415 InitializeObjectAttributes( &attr, &string, OBJ_CASE_INSENSITIVE, NULL, NULL );
2416 status = NtOpenFile( &file, SYNCHRONIZE, &attr, &io, 0, FILE_SYNCHRONOUS_IO_NONALERT );
2417 todo_wine
2418 ok( status == STATUS_UNSUCCESSFUL, "got %#x\n", status );
2420 winetest_pop_context();
2423 static void test_hid_driver( DWORD report_id, DWORD polled )
2425 #include "psh_hid_macros.h"
2426 /* Replace REPORT_ID with USAGE_PAGE when id is 0 */
2427 #define REPORT_ID_OR_USAGE_PAGE(size, id, off) SHORT_ITEM_1((id ? 8 : 0), 1, (id + off))
2428 const unsigned char report_desc[] =
2430 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
2431 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
2432 COLLECTION(1, Application),
2433 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
2434 COLLECTION(1, Logical),
2435 REPORT_ID_OR_USAGE_PAGE(1, report_id, 0),
2436 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
2437 USAGE(1, HID_USAGE_GENERIC_X),
2438 USAGE(1, HID_USAGE_GENERIC_Y),
2439 LOGICAL_MINIMUM(1, -128),
2440 LOGICAL_MAXIMUM(1, 127),
2441 REPORT_SIZE(1, 8),
2442 REPORT_COUNT(1, 2),
2443 INPUT(1, Data|Var|Abs),
2445 USAGE_PAGE(1, HID_USAGE_PAGE_BUTTON),
2446 USAGE_MINIMUM(1, 1),
2447 USAGE_MAXIMUM(1, 8),
2448 LOGICAL_MINIMUM(1, 0),
2449 LOGICAL_MAXIMUM(1, 1),
2450 REPORT_COUNT(1, 8),
2451 REPORT_SIZE(1, 1),
2452 INPUT(1, Data|Var|Abs),
2454 USAGE_MINIMUM(1, 0x18),
2455 USAGE_MAXIMUM(1, 0x1f),
2456 LOGICAL_MINIMUM(1, 0),
2457 LOGICAL_MAXIMUM(1, 1),
2458 REPORT_COUNT(1, 8),
2459 REPORT_SIZE(1, 1),
2460 INPUT(1, Cnst|Var|Abs),
2461 REPORT_COUNT(1, 8),
2462 REPORT_SIZE(1, 1),
2463 INPUT(1, Cnst|Var|Abs),
2464 /* needs to be 8 bit aligned as next has Buff */
2466 USAGE_MINIMUM(4, (HID_USAGE_PAGE_KEYBOARD<<16)|0x8),
2467 USAGE_MAXIMUM(4, (HID_USAGE_PAGE_KEYBOARD<<16)|0xf),
2468 LOGICAL_MINIMUM(1, 0),
2469 LOGICAL_MAXIMUM(1, 8),
2470 REPORT_COUNT(1, 2),
2471 REPORT_SIZE(1, 8),
2472 INPUT(2, Data|Ary|Rel|Wrap|Lin|Pref|Null|Vol|Buff),
2474 /* needs to be 8 bit aligned as previous has Buff */
2475 USAGE(1, 0x20),
2476 LOGICAL_MINIMUM(1, 0),
2477 LOGICAL_MAXIMUM(1, 1),
2478 REPORT_COUNT(1, 8),
2479 REPORT_SIZE(1, 1),
2480 INPUT(1, Data|Var|Abs),
2481 USAGE_MINIMUM(1, 0x21),
2482 USAGE_MAXIMUM(1, 0x22),
2483 REPORT_COUNT(1, 2),
2484 REPORT_SIZE(1, 0),
2485 INPUT(1, Data|Var|Abs),
2486 USAGE(1, 0x23),
2487 REPORT_COUNT(1, 0),
2488 REPORT_SIZE(1, 1),
2489 INPUT(1, Data|Var|Abs),
2491 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
2492 USAGE(1, HID_USAGE_GENERIC_HATSWITCH),
2493 LOGICAL_MINIMUM(1, 1),
2494 LOGICAL_MAXIMUM(1, 8),
2495 REPORT_SIZE(1, 4),
2496 REPORT_COUNT(1, 2),
2497 INPUT(1, Data|Var|Abs),
2499 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
2500 USAGE(1, HID_USAGE_GENERIC_Z),
2501 LOGICAL_MINIMUM(4, 0x00000000),
2502 LOGICAL_MAXIMUM(4, 0x3fffffff),
2503 PHYSICAL_MINIMUM(4, 0x80000000),
2504 PHYSICAL_MAXIMUM(4, 0x7fffffff),
2505 REPORT_SIZE(1, 32),
2506 REPORT_COUNT(1, 1),
2507 INPUT(1, Data|Var|Abs),
2509 /* reset physical range to its default interpretation */
2510 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
2511 USAGE(1, HID_USAGE_GENERIC_RX),
2512 PHYSICAL_MINIMUM(4, 0),
2513 PHYSICAL_MAXIMUM(4, 0),
2514 REPORT_SIZE(1, 32),
2515 REPORT_COUNT(1, 1),
2516 INPUT(1, Data|Var|Abs),
2518 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
2519 USAGE(1, HID_USAGE_GENERIC_RY),
2520 LOGICAL_MINIMUM(4, 0x7fff),
2521 LOGICAL_MAXIMUM(4, 0x0000),
2522 PHYSICAL_MINIMUM(4, 0x0000),
2523 PHYSICAL_MAXIMUM(4, 0x7fff),
2524 REPORT_SIZE(1, 32),
2525 REPORT_COUNT(1, 1),
2526 INPUT(1, Data|Var|Abs),
2527 END_COLLECTION,
2529 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
2530 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
2531 COLLECTION(1, Report),
2532 REPORT_ID_OR_USAGE_PAGE(1, report_id, 1),
2533 USAGE_PAGE(1, HID_USAGE_PAGE_BUTTON),
2534 USAGE_MINIMUM(1, 9),
2535 USAGE_MAXIMUM(1, 10),
2536 LOGICAL_MINIMUM(1, 0),
2537 LOGICAL_MAXIMUM(1, 1),
2538 REPORT_COUNT(1, 8),
2539 REPORT_SIZE(1, 1),
2540 INPUT(1, Data|Var|Abs),
2541 END_COLLECTION,
2543 USAGE_PAGE(1, HID_USAGE_PAGE_LED),
2544 USAGE(1, HID_USAGE_LED_GREEN),
2545 COLLECTION(1, Report),
2546 REPORT_ID_OR_USAGE_PAGE(1, report_id, 0),
2547 USAGE_PAGE(1, HID_USAGE_PAGE_LED),
2548 USAGE(1, 1),
2549 USAGE(1, 2),
2550 USAGE(1, 3),
2551 USAGE(1, 4),
2552 USAGE(1, 5),
2553 USAGE(1, 6),
2554 USAGE(1, 7),
2555 USAGE(1, 8),
2556 LOGICAL_MINIMUM(1, 0),
2557 LOGICAL_MAXIMUM(1, 1),
2558 PHYSICAL_MINIMUM(1, 0),
2559 PHYSICAL_MAXIMUM(1, 1),
2560 REPORT_COUNT(1, 8),
2561 REPORT_SIZE(1, 1),
2562 INPUT(1, Data|Var|Abs),
2564 USAGE(4, (HID_USAGE_PAGE_KEYBOARD<<16)|0x8c),
2565 USAGE(4, (HID_USAGE_PAGE_KEYBOARD<<16)|0x8d),
2566 USAGE(4, (HID_USAGE_PAGE_KEYBOARD<<16)|0x8e),
2567 USAGE(4, (HID_USAGE_PAGE_KEYBOARD<<16)|0x8f),
2568 LOGICAL_MINIMUM(1, 1),
2569 LOGICAL_MAXIMUM(1, 16),
2570 REPORT_COUNT(1, 2),
2571 REPORT_SIZE(1, 8),
2572 INPUT(1, Data|Ary|Abs),
2573 END_COLLECTION,
2575 USAGE_PAGE(2, HID_USAGE_PAGE_HAPTICS),
2576 USAGE(1, HID_USAGE_HAPTICS_SIMPLE_CONTROLLER),
2577 COLLECTION(1, Logical),
2578 REPORT_ID_OR_USAGE_PAGE(1, report_id, 0),
2579 USAGE_PAGE(2, HID_USAGE_PAGE_HAPTICS),
2581 USAGE(1, HID_USAGE_HAPTICS_WAVEFORM_LIST),
2582 COLLECTION(1, NamedArray),
2583 USAGE_PAGE(1, HID_USAGE_PAGE_ORDINAL),
2584 USAGE(1, 3), /* HID_USAGE_HAPTICS_WAVEFORM_RUMBLE */
2585 USAGE(1, 4), /* HID_USAGE_HAPTICS_WAVEFORM_BUZZ */
2586 LOGICAL_MINIMUM(2, 0x0000),
2587 LOGICAL_MAXIMUM(2, 0xffff),
2588 REPORT_COUNT(1, 2),
2589 REPORT_SIZE(1, 16),
2590 FEATURE(1, Data|Var|Abs|Null),
2591 END_COLLECTION,
2593 USAGE_PAGE(2, HID_USAGE_PAGE_HAPTICS),
2594 USAGE(1, HID_USAGE_HAPTICS_DURATION_LIST),
2595 COLLECTION(1, NamedArray),
2596 USAGE_PAGE(1, HID_USAGE_PAGE_ORDINAL),
2597 USAGE(1, 3), /* 0 (HID_USAGE_HAPTICS_WAVEFORM_RUMBLE) */
2598 USAGE(1, 4), /* 0 (HID_USAGE_HAPTICS_WAVEFORM_BUZZ) */
2599 LOGICAL_MINIMUM(2, 0x0000),
2600 LOGICAL_MAXIMUM(2, 0xffff),
2601 REPORT_COUNT(1, 2),
2602 REPORT_SIZE(1, 16),
2603 FEATURE(1, Data|Var|Abs|Null),
2604 END_COLLECTION,
2606 USAGE_PAGE(2, HID_USAGE_PAGE_HAPTICS),
2607 USAGE(1, HID_USAGE_HAPTICS_WAVEFORM_CUTOFF_TIME),
2608 UNIT(2, 0x1001), /* seconds */
2609 UNIT_EXPONENT(1, -3), /* 10^-3 */
2610 LOGICAL_MINIMUM(2, 0x8000),
2611 LOGICAL_MAXIMUM(2, 0x7fff),
2612 PHYSICAL_MINIMUM(4, 0x00000000),
2613 PHYSICAL_MAXIMUM(4, 0xffffffff),
2614 REPORT_SIZE(1, 32),
2615 REPORT_COUNT(1, 2),
2616 FEATURE(1, Data|Var|Abs),
2617 /* reset global items */
2618 UNIT(1, 0), /* None */
2619 UNIT_EXPONENT(1, 0),
2621 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
2622 USAGE(1, HID_USAGE_GENERIC_Z),
2623 LOGICAL_MINIMUM(4, 0x0000),
2624 LOGICAL_MAXIMUM(4, 0x7fff),
2625 PHYSICAL_MINIMUM(4, 0xfff90000),
2626 PHYSICAL_MAXIMUM(4, 0x0003ffff),
2627 REPORT_SIZE(1, 32),
2628 REPORT_COUNT(1, 1),
2629 FEATURE(1, Data|Var|Abs),
2630 END_COLLECTION,
2632 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
2633 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
2634 COLLECTION(1, Report),
2635 REPORT_ID_OR_USAGE_PAGE(1, report_id, 1),
2636 USAGE_PAGE(1, HID_USAGE_PAGE_BUTTON),
2637 USAGE_MINIMUM(1, 9),
2638 USAGE_MAXIMUM(1, 10),
2639 LOGICAL_MINIMUM(1, 0),
2640 LOGICAL_MAXIMUM(1, 1),
2641 PHYSICAL_MINIMUM(1, 0),
2642 PHYSICAL_MAXIMUM(1, 1),
2643 REPORT_COUNT(1, 8),
2644 REPORT_SIZE(1, 1),
2645 FEATURE(1, Data|Var|Abs),
2646 END_COLLECTION,
2648 USAGE_PAGE(1, HID_USAGE_PAGE_LED),
2649 USAGE(1, HID_USAGE_LED_GREEN),
2650 COLLECTION(1, Report),
2651 REPORT_ID_OR_USAGE_PAGE(1, report_id, 0),
2652 USAGE_PAGE(1, HID_USAGE_PAGE_LED),
2653 REPORT_COUNT(1, 8),
2654 REPORT_SIZE(1, 1),
2655 OUTPUT(1, Cnst|Var|Abs),
2656 END_COLLECTION,
2658 USAGE_PAGE(1, HID_USAGE_PAGE_LED),
2659 USAGE(1, HID_USAGE_LED_RED),
2660 COLLECTION(1, Report),
2661 REPORT_ID_OR_USAGE_PAGE(1, report_id, 1),
2662 USAGE_PAGE(1, HID_USAGE_PAGE_LED),
2663 REPORT_COUNT(1, 8),
2664 REPORT_SIZE(1, 1),
2665 OUTPUT(1, Cnst|Var|Abs),
2666 END_COLLECTION,
2667 END_COLLECTION,
2669 #undef REPORT_ID_OR_USAGE_PAGE
2670 #include "pop_hid_macros.h"
2672 static const HID_DEVICE_ATTRIBUTES attributes =
2674 .Size = sizeof(HID_DEVICE_ATTRIBUTES),
2675 .VendorID = 0x1209,
2676 .ProductID = 0x0001,
2677 .VersionNumber = 0x0100,
2679 const HIDP_CAPS caps =
2681 .Usage = HID_USAGE_GENERIC_JOYSTICK,
2682 .UsagePage = HID_USAGE_PAGE_GENERIC,
2683 .InputReportByteLength = report_id ? 25 : 26,
2684 .OutputReportByteLength = report_id ? 2 : 3,
2685 .FeatureReportByteLength = report_id ? 21 : 22,
2686 .NumberLinkCollectionNodes = 10,
2687 .NumberInputButtonCaps = 17,
2688 .NumberInputValueCaps = 7,
2689 .NumberInputDataIndices = 47,
2690 .NumberFeatureButtonCaps = 1,
2691 .NumberFeatureValueCaps = 6,
2692 .NumberFeatureDataIndices = 8,
2694 const struct hid_expect expect_in =
2696 .code = IOCTL_HID_READ_REPORT,
2697 .report_len = caps.InputReportByteLength - (report_id ? 0 : 1),
2698 .report_buf = {report_id ? report_id : 0x5a,0x5a,0x5a},
2699 .ret_length = 3,
2700 .ret_status = STATUS_SUCCESS,
2703 WCHAR cwd[MAX_PATH], tempdir[MAX_PATH];
2704 LSTATUS status;
2705 HKEY hkey;
2707 GetCurrentDirectoryW( ARRAY_SIZE(cwd), cwd );
2708 GetTempPathW( ARRAY_SIZE(tempdir), tempdir );
2709 SetCurrentDirectoryW( tempdir );
2711 status = RegCreateKeyExW( HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Services\\winetest",
2712 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL );
2713 ok( !status, "RegCreateKeyExW returned %#x\n", status );
2715 status = RegSetValueExW( hkey, L"ReportID", 0, REG_DWORD, (void *)&report_id, sizeof(report_id) );
2716 ok( !status, "RegSetValueExW returned %#x\n", status );
2718 status = RegSetValueExW( hkey, L"PolledMode", 0, REG_DWORD, (void *)&polled, sizeof(polled) );
2719 ok( !status, "RegSetValueExW returned %#x\n", status );
2721 status = RegSetValueExW( hkey, L"Descriptor", 0, REG_BINARY, (void *)report_desc, sizeof(report_desc) );
2722 ok( !status, "RegSetValueExW returned %#x\n", status );
2724 status = RegSetValueExW( hkey, L"Attributes", 0, REG_BINARY, (void *)&attributes, sizeof(attributes) );
2725 ok( !status, "RegSetValueExW returned %#x\n", status );
2727 status = RegSetValueExW( hkey, L"Caps", 0, REG_BINARY, (void *)&caps, sizeof(caps) );
2728 ok( !status, "RegSetValueExW returned %#x\n", status );
2730 status = RegSetValueExW( hkey, L"Expect", 0, REG_BINARY, NULL, 0 );
2731 ok( !status, "RegSetValueExW returned %#x\n", status );
2733 status = RegSetValueExW( hkey, L"Input", 0, REG_BINARY, (void *)&expect_in, polled ? sizeof(expect_in) : 0 );
2734 ok( !status, "RegSetValueExW returned %#x\n", status );
2736 if (pnp_driver_start( L"driver_hid.dll" )) test_hid_device( report_id, polled, &caps );
2738 pnp_driver_stop();
2739 SetCurrentDirectoryW( cwd );
2742 /* undocumented HID internal preparsed data structure */
2744 struct hidp_kdr_caps
2746 USHORT usage_page;
2747 UCHAR report_id;
2748 UCHAR start_bit;
2749 USHORT bit_size;
2750 USHORT report_count;
2751 USHORT start_byte;
2752 USHORT total_bits;
2753 ULONG bit_field;
2754 USHORT end_byte;
2755 USHORT link_collection;
2756 USAGE link_usage_page;
2757 USAGE link_usage;
2758 ULONG flags;
2759 ULONG padding[8];
2760 USAGE usage_min;
2761 USAGE usage_max;
2762 USHORT string_min;
2763 USHORT string_max;
2764 USHORT designator_min;
2765 USHORT designator_max;
2766 USHORT data_index_min;
2767 USHORT data_index_max;
2768 USHORT null_value;
2769 USHORT unknown;
2770 LONG logical_min;
2771 LONG logical_max;
2772 LONG physical_min;
2773 LONG physical_max;
2774 LONG units;
2775 LONG units_exp;
2778 /* named array continues on next caps */
2779 #define HIDP_KDR_CAPS_ARRAY_HAS_MORE 0x01
2780 #define HIDP_KDR_CAPS_IS_CONSTANT 0x02
2781 #define HIDP_KDR_CAPS_IS_BUTTON 0x04
2782 #define HIDP_KDR_CAPS_IS_ABSOLUTE 0x08
2783 #define HIDP_KDR_CAPS_IS_RANGE 0x10
2784 #define HIDP_KDR_CAPS_IS_STRING_RANGE 0x40
2785 #define HIDP_KDR_CAPS_IS_DESIGNATOR_RANGE 0x80
2787 struct hidp_kdr_node
2789 USAGE usage;
2790 USAGE usage_page;
2791 USHORT parent;
2792 USHORT number_of_children;
2793 USHORT next_sibling;
2794 USHORT first_child;
2795 ULONG collection_type;
2798 struct hidp_kdr
2800 char magic[8];
2801 USAGE usage;
2802 USAGE usage_page;
2803 USHORT unknown[2];
2804 USHORT input_caps_start;
2805 USHORT input_caps_count;
2806 USHORT input_caps_end;
2807 USHORT input_report_byte_length;
2808 USHORT output_caps_start;
2809 USHORT output_caps_count;
2810 USHORT output_caps_end;
2811 USHORT output_report_byte_length;
2812 USHORT feature_caps_start;
2813 USHORT feature_caps_count;
2814 USHORT feature_caps_end;
2815 USHORT feature_report_byte_length;
2816 USHORT caps_size;
2817 USHORT number_link_collection_nodes;
2818 struct hidp_kdr_caps caps[1];
2819 /* struct hidp_kdr_node nodes[1] */
2822 static void test_hidp_kdr(void)
2824 #include "psh_hid_macros.h"
2825 const unsigned char report_desc[] =
2827 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
2828 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
2829 COLLECTION(1, Application),
2830 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
2831 LOGICAL_MINIMUM(1, 1),
2832 LOGICAL_MAXIMUM(1, 127),
2833 PHYSICAL_MINIMUM(1, -128),
2834 PHYSICAL_MAXIMUM(1, 127),
2836 USAGE(1, HID_USAGE_GENERIC_RZ),
2837 REPORT_SIZE(1, 16),
2838 REPORT_COUNT(1, 0),
2839 FEATURE(1, Data|Var|Abs),
2840 USAGE(1, HID_USAGE_GENERIC_SLIDER),
2841 REPORT_SIZE(1, 16),
2842 REPORT_COUNT(1, 1),
2843 FEATURE(1, Data|Var|Abs),
2845 USAGE(1, HID_USAGE_GENERIC_X),
2846 REPORT_SIZE(1, 8),
2847 REPORT_COUNT(1, 1),
2848 UNIT(1, 0x100e),
2849 UNIT_EXPONENT(1, -3),
2850 INPUT(1, Data|Var|Abs),
2851 UNIT_EXPONENT(1, 0),
2852 UNIT(1, 0),
2853 USAGE(1, HID_USAGE_GENERIC_Y),
2854 DESIGNATOR_MINIMUM(1, 1),
2855 DESIGNATOR_MAXIMUM(1, 4),
2856 REPORT_SIZE(1, 8),
2857 REPORT_COUNT(1, 1),
2858 INPUT(1, Cnst|Var|Abs),
2859 USAGE(1, HID_USAGE_GENERIC_Z),
2860 REPORT_SIZE(1, 8),
2861 REPORT_COUNT(1, 1),
2862 INPUT(1, Data|Var|Rel),
2863 USAGE(1, HID_USAGE_GENERIC_RX),
2864 USAGE(1, HID_USAGE_GENERIC_RY),
2865 REPORT_SIZE(1, 16),
2866 REPORT_COUNT(1, 2),
2867 LOGICAL_MINIMUM(1, 7),
2868 INPUT(1, Data|Var|Abs|Null),
2870 COLLECTION(1, Application),
2871 USAGE(4, (HID_USAGE_PAGE_BUTTON << 16)|1),
2872 USAGE(4, (HID_USAGE_PAGE_BUTTON << 16)|2),
2873 REPORT_SIZE(1, 1),
2874 REPORT_COUNT(1, 8),
2875 LOGICAL_MINIMUM(1, 0),
2876 LOGICAL_MAXIMUM(1, 1),
2877 INPUT(1, Data|Var|Abs),
2879 USAGE_MINIMUM(4, (HID_USAGE_PAGE_BUTTON << 16)|3),
2880 USAGE_MAXIMUM(4, (HID_USAGE_PAGE_BUTTON << 16)|8),
2881 REPORT_SIZE(1, 8),
2882 REPORT_COUNT(1, 1),
2883 LOGICAL_MINIMUM(1, 3),
2884 LOGICAL_MAXIMUM(1, 8),
2885 INPUT(1, Data|Ary|Abs),
2887 USAGE_MINIMUM(4, (HID_USAGE_PAGE_BUTTON << 16)|9),
2888 USAGE_MAXIMUM(4, (HID_USAGE_PAGE_BUTTON << 16)|12),
2889 REPORT_SIZE(1, 8),
2890 REPORT_COUNT(1, 4),
2891 LOGICAL_MINIMUM(1, 9),
2892 LOGICAL_MAXIMUM(1, 12),
2893 INPUT(2, Data|Ary|Abs|Buff),
2895 USAGE(4, (HID_USAGE_PAGE_BUTTON << 16)|13),
2896 USAGE(4, (HID_USAGE_PAGE_BUTTON << 16)|14),
2897 USAGE(4, (HID_USAGE_PAGE_BUTTON << 16)|15),
2898 USAGE(4, (HID_USAGE_PAGE_BUTTON << 16)|16),
2899 REPORT_SIZE(1, 8),
2900 REPORT_COUNT(1, 1),
2901 LOGICAL_MINIMUM(1, 13),
2902 LOGICAL_MAXIMUM(1, 16),
2903 INPUT(1, Data|Ary|Abs),
2904 END_COLLECTION,
2905 END_COLLECTION,
2907 #include "pop_hid_macros.h"
2909 static const HIDP_CAPS expect_hidp_caps =
2911 .Usage = HID_USAGE_GENERIC_JOYSTICK,
2912 .UsagePage = HID_USAGE_PAGE_GENERIC,
2913 .InputReportByteLength = 15,
2915 static const HID_DEVICE_ATTRIBUTES attributes =
2917 .Size = sizeof(HID_DEVICE_ATTRIBUTES),
2918 .VendorID = 0x1209,
2919 .ProductID = 0x0001,
2920 .VersionNumber = 0x0100,
2922 static const struct hidp_kdr expect_kdr =
2924 .magic = "HidP KDR",
2925 .usage = 0x04,
2926 .usage_page = 0x01,
2927 .input_caps_count = 13,
2928 .input_caps_end = 13,
2929 .input_report_byte_length = 15,
2930 .output_caps_start = 13,
2931 .output_caps_end = 13,
2932 .feature_caps_start = 13,
2933 .feature_caps_count = 2,
2934 .feature_caps_end = 14,
2935 .feature_report_byte_length = 3,
2936 .caps_size = 1560,
2937 .number_link_collection_nodes = 2,
2939 static const struct hidp_kdr_caps expect_caps[] =
2942 .usage_page = 0x01, .bit_size = 0x08, .report_count = 0x1, .start_byte = 0x1, .total_bits = 0x08,
2943 .bit_field = 0x002, .end_byte = 0x2, .link_usage_page = 0x01, .link_usage = 0x04, .flags = 0x08,
2944 .usage_min = 0x30, .usage_max = 0x30, .logical_min = 1, .logical_max = 127, .physical_min = -128,
2945 .physical_max = 127, .units = 0xe, .units_exp = -3
2948 .usage_page = 0x01, .bit_size = 0x08, .report_count = 0x1, .start_byte = 0x2, .total_bits = 0x08,
2949 .bit_field = 0x003, .end_byte = 0x3, .link_usage_page = 0x01, .link_usage = 0x04, .flags = 0x8a,
2950 .usage_min = 0x31, .usage_max = 0x31, .designator_min = 1, .designator_max = 4, .data_index_min = 0x01,
2951 .data_index_max = 0x01, .logical_min = 1, .logical_max = 127, .physical_min = -128, .physical_max = 127
2954 .usage_page = 0x01, .bit_size = 0x08, .report_count = 0x1, .start_byte = 0x3, .total_bits = 0x08,
2955 .bit_field = 0x006, .end_byte = 0x4, .link_usage_page = 0x01, .link_usage = 0x04, .usage_min = 0x32,
2956 .usage_max = 0x32, .data_index_min = 0x02, .data_index_max = 0x02, .logical_min = 1, .logical_max = 127,
2957 .physical_min = -128, .physical_max = 127
2960 .usage_page = 0x01, .bit_size = 0x10, .report_count = 0x1, .start_byte = 0x6, .total_bits = 0x10,
2961 .bit_field = 0x042, .end_byte = 0x8, .link_usage_page = 0x01, .link_usage = 0x04, .flags = 0x08,
2962 .usage_min = 0x34, .usage_max = 0x34, .data_index_min = 0x03, .data_index_max = 0x03, .null_value = 1,
2963 .logical_min = 7, .logical_max = 127, .physical_min = -128, .physical_max = 127
2966 .usage_page = 0x01, .bit_size = 0x10, .report_count = 0x1, .start_byte = 0x4, .total_bits = 0x10,
2967 .bit_field = 0x042, .end_byte = 0x6, .link_usage_page = 0x01, .link_usage = 0x04, .flags = 0x08,
2968 .usage_min = 0x33, .usage_max = 0x33, .data_index_min = 0x04, .data_index_max = 0x04, .null_value = 1,
2969 .logical_min = 7, .logical_max = 127, .physical_min = -128, .physical_max = 127
2972 .usage_page = 0x09, .start_bit = 1, .bit_size = 0x01, .report_count = 0x7, .start_byte = 0x8, .total_bits = 0x07,
2973 .bit_field = 0x002, .end_byte = 0x9, .link_collection = 1, .link_usage_page = 0x01, .flags = 0x0c,
2974 .usage_min = 0x02, .usage_max = 0x02, .data_index_min = 0x05, .data_index_max = 0x05,
2977 .usage_page = 0x09, .bit_size = 0x01, .report_count = 0x1, .start_byte = 0x8, .total_bits = 0x01,
2978 .bit_field = 0x002, .end_byte = 0x9, .link_collection = 1, .link_usage_page = 0x01, .flags = 0x0c,
2979 .usage_min = 0x01, .usage_max = 0x01, .data_index_min = 0x06, .data_index_max = 0x06,
2982 .usage_page = 0x09, .bit_size = 0x08, .report_count = 0x1, .start_byte = 0x9, .total_bits = 0x08,
2983 .bit_field = 0x000, .end_byte = 0xa, .link_collection = 1, .link_usage_page = 0x01, .flags = 0x1c,
2984 .usage_min = 0x03, .usage_max = 0x08, .data_index_min = 0x07, .data_index_max = 0x0c, .null_value = 3,
2985 .logical_min = 8
2988 .usage_page = 0x09, .bit_size = 0x08, .report_count = 0x4, .start_byte = 0xa, .total_bits = 0x20,
2989 .bit_field = 0x100, .end_byte = 0xe, .link_collection = 1, .link_usage_page = 0x01, .flags = 0x1c,
2990 .usage_min = 0x09, .usage_max = 0x0c, .data_index_min = 0x0d, .data_index_max = 0x10, .null_value = 9,
2991 .logical_min = 12
2994 .usage_page = 0x09, .bit_size = 0x08, .report_count = 0x1, .start_byte = 0xe, .total_bits = 0x08,
2995 .bit_field = 0x000, .end_byte = 0xf, .link_collection = 1, .link_usage_page = 0x01, .flags = 0x0d,
2996 .usage_min = 0x10, .usage_max = 0x10, .data_index_min = 0x14, .data_index_max = 0x14, .null_value = 13,
2997 .logical_min = 16
3000 .usage_page = 0x09, .bit_size = 0x08, .report_count = 0x1, .start_byte = 0xe, .total_bits = 0x08,
3001 .bit_field = 0x000, .end_byte = 0xf, .link_collection = 1, .link_usage_page = 0x01, .flags = 0x0d,
3002 .usage_min = 0x0f, .usage_max = 0x0f, .data_index_min = 0x13, .data_index_max = 0x13, .null_value = 13,
3003 .logical_min = 16
3006 .usage_page = 0x09, .bit_size = 0x08, .report_count = 0x1, .start_byte = 0xe, .total_bits = 0x08,
3007 .bit_field = 0x000, .end_byte = 0xf, .link_collection = 1, .link_usage_page = 0x01, .flags = 0x0d,
3008 .usage_min = 0x0e, .usage_max = 0x0e, .data_index_min = 0x12, .data_index_max = 0x12, .null_value = 13,
3009 .logical_min = 16
3012 .usage_page = 0x09, .bit_size = 0x08, .report_count = 0x1, .start_byte = 0xe, .total_bits = 0x08,
3013 .bit_field = 0x000, .end_byte = 0xf, .link_collection = 1, .link_usage_page = 0x01, .flags = 0x0c,
3014 .usage_min = 0x0d, .usage_max = 0x0d, .data_index_min = 0x11, .data_index_max = 0x11, .null_value = 13,
3015 .logical_min = 16
3018 .usage_page = 0x01, .bit_size = 0x10, .report_count = 0x1, .start_byte = 0x1, .total_bits = 0x10,
3019 .bit_field = 0x002, .end_byte = 0x3, .link_usage_page = 0x01, .link_usage = 0x04, .flags = 0x08,
3020 .usage_min = 0x36, .usage_max = 0x36, .logical_min = 1, .logical_max = 127, .physical_min = -128,
3021 .physical_max = 127
3026 static const struct hidp_kdr_node expect_nodes[] =
3029 .usage = 0x04,
3030 .usage_page = 0x01,
3031 .parent = 0,
3032 .number_of_children = 0x1,
3033 .next_sibling = 0,
3034 .first_child = 0x1,
3035 .collection_type = 0x1,
3038 .usage = 0x00,
3039 .usage_page = 0x01,
3040 .parent = 0,
3041 .number_of_children = 0,
3042 .next_sibling = 0,
3043 .first_child = 0,
3044 .collection_type = 0x1,
3048 char buffer[FIELD_OFFSET( SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath[MAX_PATH] )];
3049 SP_DEVICE_INTERFACE_DATA iface = {sizeof(SP_DEVICE_INTERFACE_DATA)};
3050 SP_DEVICE_INTERFACE_DETAIL_DATA_W *iface_detail = (void *)buffer;
3051 SP_DEVINFO_DATA device = {sizeof(SP_DEVINFO_DATA)};
3052 WCHAR cwd[MAX_PATH], tempdir[MAX_PATH];
3053 PHIDP_PREPARSED_DATA preparsed_data;
3054 DWORD i, report_id = 0, polled = 0;
3055 struct hidp_kdr *kdr;
3056 LSTATUS status;
3057 HDEVINFO set;
3058 HANDLE file;
3059 HKEY hkey;
3060 BOOL ret;
3062 GetCurrentDirectoryW( ARRAY_SIZE(cwd), cwd );
3063 GetTempPathW( ARRAY_SIZE(tempdir), tempdir );
3064 SetCurrentDirectoryW( tempdir );
3066 status = RegCreateKeyExW( HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Services\\winetest",
3067 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL );
3068 ok( !status, "RegCreateKeyExW returned %#x\n", status );
3070 status = RegSetValueExW( hkey, L"ReportID", 0, REG_DWORD, (void *)&report_id, sizeof(report_id) );
3071 ok( !status, "RegSetValueExW returned %#x\n", status );
3073 status = RegSetValueExW( hkey, L"PolledMode", 0, REG_DWORD, (void *)&polled, sizeof(polled) );
3074 ok( !status, "RegSetValueExW returned %#x\n", status );
3076 status = RegSetValueExW( hkey, L"Descriptor", 0, REG_BINARY, (void *)report_desc, sizeof(report_desc) );
3077 ok( !status, "RegSetValueExW returned %#x\n", status );
3079 status = RegSetValueExW( hkey, L"Attributes", 0, REG_BINARY, (void *)&attributes, sizeof(attributes) );
3080 ok( !status, "RegSetValueExW returned %#x\n", status );
3082 status = RegSetValueExW( hkey, L"Caps", 0, REG_BINARY, (void *)&expect_hidp_caps, sizeof(expect_hidp_caps) );
3083 ok( !status, "RegSetValueExW returned %#x\n", status );
3085 status = RegSetValueExW( hkey, L"Expect", 0, REG_BINARY, NULL, 0 );
3086 ok( !status, "RegSetValueExW returned %#x\n", status );
3088 status = RegSetValueExW( hkey, L"Input", 0, REG_BINARY, NULL, 0 );
3089 ok( !status, "RegSetValueExW returned %#x\n", status );
3091 if (!pnp_driver_start( L"driver_hid.dll" )) goto done;
3093 set = SetupDiGetClassDevsW( &GUID_DEVINTERFACE_HID, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT );
3094 ok( set != INVALID_HANDLE_VALUE, "failed to get device list, error %#x\n", GetLastError() );
3095 for (i = 0; SetupDiEnumDeviceInfo( set, i, &device ); ++i)
3097 ret = SetupDiEnumDeviceInterfaces( set, &device, &GUID_DEVINTERFACE_HID, 0, &iface );
3098 ok( ret, "failed to get interface, error %#x\n", GetLastError() );
3099 ok( IsEqualGUID( &iface.InterfaceClassGuid, &GUID_DEVINTERFACE_HID ), "wrong class %s\n",
3100 debugstr_guid( &iface.InterfaceClassGuid ) );
3101 ok( iface.Flags == SPINT_ACTIVE, "got flags %#x\n", iface.Flags );
3103 iface_detail->cbSize = sizeof(*iface_detail);
3104 ret = SetupDiGetDeviceInterfaceDetailW( set, &iface, iface_detail, sizeof(buffer), NULL, NULL );
3105 ok( ret, "failed to get interface path, error %#x\n", GetLastError() );
3107 if (wcsstr( iface_detail->DevicePath, L"\\\\?\\hid#winetest#1" )) break;
3109 SetupDiDestroyDeviceInfoList( set );
3111 file = CreateFileW( iface_detail->DevicePath, FILE_READ_ACCESS | FILE_WRITE_ACCESS,
3112 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
3113 ok( file != INVALID_HANDLE_VALUE, "got error %u\n", GetLastError() );
3115 ret = HidD_GetPreparsedData( file, &preparsed_data );
3116 ok( ret, "HidD_GetPreparsedData failed with error %u\n", GetLastError() );
3118 kdr = (struct hidp_kdr *)preparsed_data;
3119 todo_wine
3120 ok( !strncmp( kdr->magic, expect_kdr.magic, 8 ), "got %s expected %s\n",
3121 debugstr_an(kdr->magic, 8), debugstr_an(expect_kdr.magic, 8) );
3123 if (!strncmp( kdr->magic, expect_kdr.magic, 8 ))
3125 check_member( *kdr, expect_kdr, "%04x", usage );
3126 check_member( *kdr, expect_kdr, "%04x", usage_page );
3127 check_member( *kdr, expect_kdr, "%#x", unknown[0] );
3128 check_member( *kdr, expect_kdr, "%#x", unknown[1] );
3129 check_member( *kdr, expect_kdr, "%d", input_caps_start );
3130 check_member( *kdr, expect_kdr, "%d", input_caps_count );
3131 check_member( *kdr, expect_kdr, "%d", input_caps_end );
3132 check_member( *kdr, expect_kdr, "%d", input_report_byte_length );
3133 check_member( *kdr, expect_kdr, "%d", output_caps_start );
3134 check_member( *kdr, expect_kdr, "%d", output_caps_count );
3135 check_member( *kdr, expect_kdr, "%d", output_caps_end );
3136 check_member( *kdr, expect_kdr, "%d", output_report_byte_length );
3137 check_member( *kdr, expect_kdr, "%d", feature_caps_start );
3138 check_member( *kdr, expect_kdr, "%d", feature_caps_count );
3139 check_member( *kdr, expect_kdr, "%d", feature_caps_end );
3140 check_member( *kdr, expect_kdr, "%d", feature_report_byte_length );
3141 check_member( *kdr, expect_kdr, "%d", caps_size );
3142 check_member( *kdr, expect_kdr, "%d", number_link_collection_nodes );
3144 for (i = 0; i < ARRAY_SIZE(expect_caps); ++i)
3146 winetest_push_context( "caps[%d]", i );
3147 check_member( kdr->caps[i], expect_caps[i], "%04x", usage_page );
3148 check_member( kdr->caps[i], expect_caps[i], "%d", report_id );
3149 check_member( kdr->caps[i], expect_caps[i], "%d", start_bit );
3150 check_member( kdr->caps[i], expect_caps[i], "%d", bit_size );
3151 check_member( kdr->caps[i], expect_caps[i], "%d", report_count );
3152 check_member( kdr->caps[i], expect_caps[i], "%d", start_byte );
3153 check_member( kdr->caps[i], expect_caps[i], "%d", total_bits );
3154 check_member( kdr->caps[i], expect_caps[i], "%#x", bit_field );
3155 check_member( kdr->caps[i], expect_caps[i], "%d", end_byte );
3156 check_member( kdr->caps[i], expect_caps[i], "%d", link_collection );
3157 check_member( kdr->caps[i], expect_caps[i], "%04x", link_usage_page );
3158 check_member( kdr->caps[i], expect_caps[i], "%04x", link_usage );
3159 check_member( kdr->caps[i], expect_caps[i], "%#x", flags );
3160 check_member( kdr->caps[i], expect_caps[i], "%#x", padding[0] );
3161 check_member( kdr->caps[i], expect_caps[i], "%#x", padding[1] );
3162 check_member( kdr->caps[i], expect_caps[i], "%#x", padding[2] );
3163 check_member( kdr->caps[i], expect_caps[i], "%#x", padding[3] );
3164 check_member( kdr->caps[i], expect_caps[i], "%#x", padding[4] );
3165 check_member( kdr->caps[i], expect_caps[i], "%#x", padding[5] );
3166 check_member( kdr->caps[i], expect_caps[i], "%#x", padding[6] );
3167 check_member( kdr->caps[i], expect_caps[i], "%#x", padding[7] );
3168 check_member( kdr->caps[i], expect_caps[i], "%04x", usage_min );
3169 check_member( kdr->caps[i], expect_caps[i], "%04x", usage_max );
3170 check_member( kdr->caps[i], expect_caps[i], "%d", string_min );
3171 check_member( kdr->caps[i], expect_caps[i], "%d", string_max );
3172 check_member( kdr->caps[i], expect_caps[i], "%d", designator_min );
3173 check_member( kdr->caps[i], expect_caps[i], "%d", designator_max );
3174 check_member( kdr->caps[i], expect_caps[i], "%#x", data_index_min );
3175 check_member( kdr->caps[i], expect_caps[i], "%#x", data_index_max );
3176 check_member( kdr->caps[i], expect_caps[i], "%d", null_value );
3177 check_member( kdr->caps[i], expect_caps[i], "%d", unknown );
3178 check_member( kdr->caps[i], expect_caps[i], "%d", logical_min );
3179 check_member( kdr->caps[i], expect_caps[i], "%d", logical_max );
3180 check_member( kdr->caps[i], expect_caps[i], "%d", physical_min );
3181 check_member( kdr->caps[i], expect_caps[i], "%d", physical_max );
3182 check_member( kdr->caps[i], expect_caps[i], "%#x", units );
3183 check_member( kdr->caps[i], expect_caps[i], "%#x", units_exp );
3184 winetest_pop_context();
3187 for (i = 0; i < ARRAY_SIZE(expect_nodes); ++i)
3189 struct hidp_kdr_node *nodes = (struct hidp_kdr_node *)((char *)kdr->caps + kdr->caps_size);
3190 winetest_push_context( "nodes[%d]", i );
3191 check_member( nodes[i], expect_nodes[i], "%04x", usage );
3192 check_member( nodes[i], expect_nodes[i], "%04x", usage_page );
3193 check_member( nodes[i], expect_nodes[i], "%d", parent );
3194 check_member( nodes[i], expect_nodes[i], "%d", number_of_children );
3195 check_member( nodes[i], expect_nodes[i], "%d", next_sibling );
3196 check_member( nodes[i], expect_nodes[i], "%d", first_child );
3197 check_member( nodes[i], expect_nodes[i], "%#x", collection_type );
3198 winetest_pop_context();
3202 HidD_FreePreparsedData( preparsed_data );
3204 CloseHandle( file );
3206 done:
3207 pnp_driver_stop();
3208 SetCurrentDirectoryW( cwd );
3211 static void cleanup_registry_keys(void)
3213 static const WCHAR joystick_oem_path[] = L"System\\CurrentControlSet\\Control\\MediaProperties\\"
3214 "PrivateProperties\\Joystick\\OEM";
3215 static const WCHAR dinput_path[] = L"System\\CurrentControlSet\\Control\\MediaProperties\\"
3216 "PrivateProperties\\DirectInput";
3217 HKEY root_key;
3219 /* These keys are automatically created by DInput and they store the
3220 list of supported force-feedback effects. OEM drivers are supposed
3221 to provide a list in HKLM for the vendor-specific force-feedback
3222 support.
3224 We need to clean them up, or DInput will not refresh the list of
3225 effects from the PID report changes.
3227 RegCreateKeyExW( HKEY_CURRENT_USER, joystick_oem_path, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &root_key, NULL );
3228 RegDeleteTreeW( root_key, expect_vidpid_str );
3229 RegCloseKey( root_key );
3231 RegCreateKeyExW( HKEY_CURRENT_USER, dinput_path, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &root_key, NULL );
3232 RegDeleteTreeW( root_key, expect_vidpid_str );
3233 RegCloseKey( root_key );
3235 RegCreateKeyExW( HKEY_LOCAL_MACHINE, joystick_oem_path, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &root_key, NULL );
3236 RegDeleteTreeW( root_key, expect_vidpid_str );
3237 RegCloseKey( root_key );
3239 RegCreateKeyExW( HKEY_LOCAL_MACHINE, dinput_path, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &root_key, NULL );
3240 RegDeleteTreeW( root_key, expect_vidpid_str );
3241 RegCloseKey( root_key );
3244 static BOOL dinput_driver_start( const BYTE *desc_buf, ULONG desc_len, const HIDP_CAPS *caps )
3246 static const HID_DEVICE_ATTRIBUTES attributes =
3248 .Size = sizeof(HID_DEVICE_ATTRIBUTES),
3249 .VendorID = LOWORD( EXPECT_VIDPID ),
3250 .ProductID = HIWORD( EXPECT_VIDPID ),
3251 .VersionNumber = 0x0100,
3253 DWORD report_id = 1;
3254 DWORD polled = 0;
3255 LSTATUS status;
3256 HKEY hkey;
3258 status = RegCreateKeyExW( HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Services\\winetest",
3259 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL );
3260 ok( !status, "RegCreateKeyExW returned %#x\n", status );
3261 status = RegSetValueExW( hkey, L"ReportID", 0, REG_DWORD, (void *)&report_id, sizeof(report_id) );
3262 ok( !status, "RegSetValueExW returned %#x\n", status );
3263 status = RegSetValueExW( hkey, L"PolledMode", 0, REG_DWORD, (void *)&polled, sizeof(polled) );
3264 ok( !status, "RegSetValueExW returned %#x\n", status );
3265 status = RegSetValueExW( hkey, L"Descriptor", 0, REG_BINARY, (void *)desc_buf, desc_len );
3266 ok( !status, "RegSetValueExW returned %#x\n", status );
3267 status = RegSetValueExW( hkey, L"Attributes", 0, REG_BINARY, (void *)&attributes, sizeof(attributes) );
3268 ok( !status, "RegSetValueExW returned %#x\n", status );
3269 status = RegSetValueExW( hkey, L"Caps", 0, REG_BINARY, (void *)caps, sizeof(*caps) );
3270 ok( !status, "RegSetValueExW returned %#x\n", status );
3271 status = RegSetValueExW( hkey, L"Expect", 0, REG_BINARY, NULL, 0 );
3272 ok( !status, "RegSetValueExW returned %#x\n", status );
3273 status = RegSetValueExW( hkey, L"Input", 0, REG_BINARY, NULL, 0 );
3274 ok( !status, "RegSetValueExW returned %#x\n", status );
3276 return pnp_driver_start( L"driver_hid.dll" );
3279 static BOOL CALLBACK find_test_device( const DIDEVICEINSTANCEW *devinst, void *context )
3281 if (IsEqualGUID( &devinst->guidProduct, &expect_guid_product ))
3282 *(DIDEVICEINSTANCEW *)context = *devinst;
3283 return DIENUM_CONTINUE;
3286 struct check_objects_todos
3288 BOOL ofs;
3289 BOOL type;
3290 BOOL collection_number;
3293 struct check_objects_params
3295 UINT index;
3296 UINT expect_count;
3297 const DIDEVICEOBJECTINSTANCEW *expect_objs;
3298 const struct check_objects_todos *todo_objs;
3301 static BOOL CALLBACK check_objects( const DIDEVICEOBJECTINSTANCEW *obj, void *args )
3303 static const DIDEVICEOBJECTINSTANCEW unexpected_obj = {0};
3304 struct check_objects_params *params = args;
3305 const DIDEVICEOBJECTINSTANCEW *exp = params->expect_objs + params->index;
3306 const struct check_objects_todos *todo = params->todo_objs + params->index;
3308 winetest_push_context( "obj[%d]", params->index );
3310 ok( params->index < params->expect_count, "unexpected extra object\n" );
3311 if (params->index >= params->expect_count) exp = &unexpected_obj;
3313 check_member( *obj, *exp, "%u", dwSize );
3314 check_member_guid( *obj, *exp, guidType );
3315 todo_wine_if( todo->ofs )
3316 check_member( *obj, *exp, "%#x", dwOfs );
3317 todo_wine_if( todo->type )
3318 check_member( *obj, *exp, "%#x", dwType );
3319 check_member( *obj, *exp, "%#x", dwFlags );
3320 if (!localized) todo_wine check_member_wstr( *obj, *exp, tszName );
3321 check_member( *obj, *exp, "%u", dwFFMaxForce );
3322 check_member( *obj, *exp, "%u", dwFFForceResolution );
3323 todo_wine_if( todo->collection_number )
3324 check_member( *obj, *exp, "%u", wCollectionNumber );
3325 check_member( *obj, *exp, "%u", wDesignatorIndex );
3326 check_member( *obj, *exp, "%#04x", wUsagePage );
3327 check_member( *obj, *exp, "%#04x", wUsage );
3328 check_member( *obj, *exp, "%#04x", dwDimension );
3329 check_member( *obj, *exp, "%#04x", wExponent );
3330 check_member( *obj, *exp, "%u", wReportId );
3332 winetest_pop_context();
3334 params->index++;
3335 return DIENUM_CONTINUE;
3338 static BOOL CALLBACK check_object_count( const DIDEVICEOBJECTINSTANCEW *obj, void *args )
3340 DWORD *count = args;
3341 *count = *count + 1;
3342 return DIENUM_CONTINUE;
3345 static void test_simple_joystick(void)
3347 #include "psh_hid_macros.h"
3348 static const unsigned char report_desc[] =
3350 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
3351 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
3352 COLLECTION(1, Application),
3353 USAGE(1, HID_USAGE_GENERIC_JOYSTICK),
3354 COLLECTION(1, Report),
3355 REPORT_ID(1, 1),
3357 USAGE(1, HID_USAGE_GENERIC_X),
3358 USAGE(1, HID_USAGE_GENERIC_Y),
3359 LOGICAL_MINIMUM(1, 0xe7),
3360 LOGICAL_MAXIMUM(1, 0x38),
3361 PHYSICAL_MINIMUM(1, 0xe7),
3362 PHYSICAL_MAXIMUM(1, 0x38),
3363 REPORT_SIZE(1, 8),
3364 REPORT_COUNT(1, 2),
3365 INPUT(1, Data|Var|Abs),
3367 USAGE(1, HID_USAGE_GENERIC_HATSWITCH),
3368 LOGICAL_MINIMUM(1, 1),
3369 LOGICAL_MAXIMUM(1, 8),
3370 PHYSICAL_MINIMUM(1, 0),
3371 PHYSICAL_MAXIMUM(1, 8),
3372 REPORT_SIZE(1, 4),
3373 REPORT_COUNT(1, 1),
3374 INPUT(1, Data|Var|Abs|Null),
3376 USAGE_PAGE(1, HID_USAGE_PAGE_BUTTON),
3377 USAGE_MINIMUM(1, 1),
3378 USAGE_MAXIMUM(1, 2),
3379 LOGICAL_MINIMUM(1, 0),
3380 LOGICAL_MAXIMUM(1, 1),
3381 PHYSICAL_MINIMUM(1, 0),
3382 PHYSICAL_MAXIMUM(1, 1),
3383 REPORT_SIZE(1, 1),
3384 REPORT_COUNT(1, 4),
3385 INPUT(1, Data|Var|Abs),
3386 END_COLLECTION,
3387 END_COLLECTION,
3389 #undef REPORT_ID_OR_USAGE_PAGE
3390 #include "pop_hid_macros.h"
3392 static const HIDP_CAPS hid_caps =
3394 .InputReportByteLength = 4,
3396 static const DIDEVCAPS expect_caps =
3398 .dwSize = sizeof(DIDEVCAPS),
3399 .dwFlags = DIDC_ATTACHED | DIDC_EMULATED,
3400 .dwDevType = DIDEVTYPE_HID | (DI8DEVTYPEJOYSTICK_LIMITED << 8) | DI8DEVTYPE_JOYSTICK,
3401 .dwAxes = 2,
3402 .dwPOVs = 1,
3403 .dwButtons = 2,
3405 struct hid_expect injected_input[] =
3408 .code = IOCTL_HID_READ_REPORT,
3409 .report_buf = {1,0x10,0x10,0},
3412 .code = IOCTL_HID_READ_REPORT,
3413 .report_buf = {1,0x38,0x38,0xf8},
3416 .code = IOCTL_HID_READ_REPORT,
3417 .report_buf = {1,0x01,0x01,0x00},
3420 .code = IOCTL_HID_READ_REPORT,
3421 .report_buf = {1,0x01,0x01,0x00},
3424 .code = IOCTL_HID_READ_REPORT,
3425 .report_buf = {1,0x80,0x80,0xff},
3428 .code = IOCTL_HID_READ_REPORT,
3429 .report_buf = {1,0x10,0xee,0x54},
3432 static const struct DIJOYSTATE2 expect_state[] =
3434 {.lX = 32767, .lY = 32767, .rgdwPOV = {-1, -1, -1, -1}, .rgbButtons = {0, 0}},
3435 {.lX = 32767, .lY = 32767, .rgdwPOV = {-1, -1, -1, -1}, .rgbButtons = {0, 0}},
3436 {.lX = 65535, .lY = 65535, .rgdwPOV = {31500, -1, -1, -1}, .rgbButtons = {0x80, 0x80}},
3437 {.lX = 20779, .lY = 20779, .rgdwPOV = {-1, -1, -1, -1}, .rgbButtons = {0, 0}},
3438 {.lX = 20779, .lY = 20779, .rgdwPOV = {-1, -1, -1, -1}, .rgbButtons = {0, 0}},
3439 {.lX = 0, .lY = 0, .rgdwPOV = {-1, -1, -1, -1}, .rgbButtons = {0x80, 0x80}},
3440 {.lX = 32767, .lY = 5594, .rgdwPOV = {13500, -1, -1, -1}, .rgbButtons = {0x80}},
3442 static const struct DIJOYSTATE2 expect_state_abs[] =
3444 {.lX = -9000, .lY = 26000, .rgdwPOV = {-1, -1, -1, -1}, .rgbButtons = {0, 0}},
3445 {.lX = -9000, .lY = 26000, .rgdwPOV = {-1, -1, -1, -1}, .rgbButtons = {0, 0}},
3446 {.lX = -4000, .lY = 51000, .rgdwPOV = {31500, -1, -1, -1}, .rgbButtons = {0x80, 0x80}},
3447 {.lX = -10667, .lY = 12905, .rgdwPOV = {-1, -1, -1, -1}, .rgbButtons = {0, 0}},
3448 {.lX = -10667, .lY = 12905, .rgdwPOV = {-1, -1, -1, -1}, .rgbButtons = {0, 0}},
3449 {.lX = -14000, .lY = 1000, .rgdwPOV = {-1, -1, -1, -1}, .rgbButtons = {0x80, 0x80}},
3450 {.lX = -9000, .lY = 1000, .rgdwPOV = {13500, -1, -1, -1}, .rgbButtons = {0x80}},
3452 static const struct DIJOYSTATE2 expect_state_rel[] =
3454 {.lX = 0, .lY = 0, .rgdwPOV = {13500, -1, -1, -1}, .rgbButtons = {0x80, 0}},
3455 {.lX = 9016, .lY = -984, .rgdwPOV = {-1, -1, -1, -1}, .rgbButtons = {0, 0}},
3456 {.lX = 40, .lY = 40, .rgdwPOV = {31500, -1, -1, -1}, .rgbButtons = {0x80, 0x80}},
3457 {.lX = -55, .lY = -55, .rgdwPOV = {-1, -1, -1, -1}, .rgbButtons = {0, 0}},
3458 {.lX = 0, .lY = 0, .rgdwPOV = {-1, -1, -1, -1}, .rgbButtons = {0, 0}},
3459 {.lX = -129, .lY = -129, .rgdwPOV = {-1, -1, -1, -1}, .rgbButtons = {0x80, 0x80}},
3460 {.lX = 144, .lY = 110, .rgdwPOV = {13500, -1, -1, -1}, .rgbButtons = {0x80}},
3462 static const DIDEVICEOBJECTDATA expect_objdata[] =
3464 {.dwOfs = 0x4, .dwData = 0xffff, .dwSequence = 0xa},
3465 {.dwOfs = 0x4, .dwData = 0xffff, .dwSequence = 0xa},
3466 {.dwOfs = 0, .dwData = 0xffff, .dwSequence = 0xa},
3467 {.dwOfs = 0x20, .dwData = 31500, .dwSequence = 0xa},
3468 {.dwOfs = 0x30, .dwData = 0x80, .dwSequence = 0xa},
3469 {.dwOfs = 0x4, .dwData = 0x512b, .dwSequence = 0xd},
3470 {.dwOfs = 0, .dwData = 0x512b, .dwSequence = 0xd},
3471 {.dwOfs = 0x20, .dwData = -1, .dwSequence = 0xd},
3472 {.dwOfs = 0x30, .dwData = 0, .dwSequence = 0xd},
3473 {.dwOfs = 0x31, .dwData = 0, .dwSequence = 0xd},
3474 {.dwOfs = 0x4, .dwData = 0, .dwSequence = 0xf},
3475 {.dwOfs = 0, .dwData = 0, .dwSequence = 0xf},
3476 {.dwOfs = 0x30, .dwData = 0x80, .dwSequence = 0xf},
3477 {.dwOfs = 0x31, .dwData = 0x80, .dwSequence = 0xf},
3480 const DIDEVICEINSTANCEW expect_devinst =
3482 .dwSize = sizeof(DIDEVICEINSTANCEW),
3483 .guidInstance = expect_guid_product,
3484 .guidProduct = expect_guid_product,
3485 .dwDevType = DIDEVTYPE_HID | (DI8DEVTYPEJOYSTICK_LIMITED << 8) | DI8DEVTYPE_JOYSTICK,
3486 .tszInstanceName = L"Wine test root driver",
3487 .tszProductName = L"Wine test root driver",
3488 .guidFFDriver = GUID_NULL,
3489 .wUsagePage = HID_USAGE_PAGE_GENERIC,
3490 .wUsage = HID_USAGE_GENERIC_JOYSTICK,
3492 const DIDEVICEOBJECTINSTANCEW expect_objects[] =
3495 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
3496 .guidType = GUID_YAxis,
3497 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(1),
3498 .dwFlags = DIDOI_ASPECTPOSITION,
3499 .tszName = L"Y Axis",
3500 .wCollectionNumber = 1,
3501 .wUsagePage = HID_USAGE_PAGE_GENERIC,
3502 .wUsage = HID_USAGE_GENERIC_Y,
3503 .wReportId = 1,
3506 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
3507 .guidType = GUID_XAxis,
3508 .dwOfs = 0x4,
3509 .dwType = DIDFT_ABSAXIS|DIDFT_MAKEINSTANCE(0),
3510 .dwFlags = DIDOI_ASPECTPOSITION,
3511 .tszName = L"X Axis",
3512 .wCollectionNumber = 1,
3513 .wUsagePage = HID_USAGE_PAGE_GENERIC,
3514 .wUsage = HID_USAGE_GENERIC_X,
3515 .wReportId = 1,
3518 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
3519 .guidType = GUID_POV,
3520 .dwOfs = 0x8,
3521 .dwType = DIDFT_POV|DIDFT_MAKEINSTANCE(0),
3522 .tszName = L"Hat Switch",
3523 .wCollectionNumber = 1,
3524 .wUsagePage = HID_USAGE_PAGE_GENERIC,
3525 .wUsage = HID_USAGE_GENERIC_HATSWITCH,
3526 .wReportId = 1,
3529 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
3530 .guidType = GUID_Button,
3531 .dwOfs = 0xc,
3532 .dwType = DIDFT_PSHBUTTON|DIDFT_MAKEINSTANCE(0),
3533 .tszName = L"Button 0",
3534 .wCollectionNumber = 1,
3535 .wUsagePage = HID_USAGE_PAGE_BUTTON,
3536 .wUsage = 0x1,
3537 .wReportId = 1,
3540 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
3541 .guidType = GUID_Button,
3542 .dwOfs = 0xd,
3543 .dwType = DIDFT_PSHBUTTON|DIDFT_MAKEINSTANCE(1),
3544 .tszName = L"Button 1",
3545 .wCollectionNumber = 1,
3546 .wUsagePage = HID_USAGE_PAGE_BUTTON,
3547 .wUsage = 0x2,
3548 .wReportId = 1,
3551 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
3552 .guidType = GUID_Unknown,
3553 .dwType = DIDFT_COLLECTION|DIDFT_NODATA|DIDFT_MAKEINSTANCE(0),
3554 .tszName = L"Collection 0 - Joystick",
3555 .wUsagePage = HID_USAGE_PAGE_GENERIC,
3556 .wUsage = HID_USAGE_GENERIC_JOYSTICK,
3559 .dwSize = sizeof(DIDEVICEOBJECTINSTANCEW),
3560 .guidType = GUID_Unknown,
3561 .dwType = DIDFT_COLLECTION|DIDFT_NODATA|DIDFT_MAKEINSTANCE(1),
3562 .tszName = L"Collection 1 - Joystick",
3563 .wUsagePage = HID_USAGE_PAGE_GENERIC,
3564 .wUsage = HID_USAGE_GENERIC_JOYSTICK,
3567 const struct check_objects_todos objects_todos[ARRAY_SIZE(expect_objects)] =
3569 {.ofs = TRUE, .type = TRUE, .collection_number = TRUE},
3570 {.ofs = TRUE, .type = TRUE, .collection_number = TRUE},
3571 {.ofs = TRUE, .collection_number = TRUE},
3572 {.ofs = TRUE, .collection_number = TRUE},
3573 {.ofs = TRUE, .collection_number = TRUE},
3575 {.type = TRUE},
3578 struct check_objects_params check_objects_params =
3580 .expect_count = ARRAY_SIZE(expect_objects),
3581 .expect_objs = expect_objects,
3582 .todo_objs = objects_todos,
3584 DIPROPGUIDANDPATH prop_guid_path =
3586 .diph =
3588 .dwSize = sizeof(DIPROPGUIDANDPATH),
3589 .dwHeaderSize = sizeof(DIPROPHEADER),
3590 .dwHow = DIPH_DEVICE,
3593 DIPROPSTRING prop_string =
3595 .diph =
3597 .dwSize = sizeof(DIPROPSTRING),
3598 .dwHeaderSize = sizeof(DIPROPHEADER),
3599 .dwHow = DIPH_DEVICE,
3602 DIPROPDWORD prop_dword =
3604 .diph =
3606 .dwSize = sizeof(DIPROPDWORD),
3607 .dwHeaderSize = sizeof(DIPROPHEADER),
3608 .dwHow = DIPH_DEVICE,
3611 DIPROPRANGE prop_range =
3613 .diph =
3615 .dwSize = sizeof(DIPROPRANGE),
3616 .dwHeaderSize = sizeof(DIPROPHEADER),
3617 .dwHow = DIPH_DEVICE,
3620 DIPROPPOINTER prop_pointer =
3622 .diph =
3624 .dwSize = sizeof(DIPROPPOINTER),
3625 .dwHeaderSize = sizeof(DIPROPHEADER),
3628 WCHAR cwd[MAX_PATH], tempdir[MAX_PATH];
3629 DIDEVICEOBJECTDATA objdata[32] = {{0}};
3630 DIDEVICEINSTANCEW devinst = {0};
3631 DIDATAFORMAT dataformat = {0};
3632 IDirectInputDevice8W *device;
3633 DIDEVCAPS caps = {0};
3634 IDirectInput8W *di;
3635 HANDLE event, file;
3636 DIJOYSTATE2 state;
3637 ULONG i, res, ref;
3638 HRESULT hr;
3639 WCHAR *tmp;
3640 HWND hwnd;
3642 GetCurrentDirectoryW( ARRAY_SIZE(cwd), cwd );
3643 GetTempPathW( ARRAY_SIZE(tempdir), tempdir );
3644 SetCurrentDirectoryW( tempdir );
3646 cleanup_registry_keys();
3647 if (!dinput_driver_start( report_desc, sizeof(report_desc), &hid_caps )) goto done;
3649 hr = DirectInput8Create( instance, DIRECTINPUT_VERSION, &IID_IDirectInput8W, (void **)&di, NULL );
3650 if (FAILED(hr))
3652 win_skip( "DirectInput8Create returned %#x\n", hr );
3653 goto done;
3656 hr = IDirectInput8_EnumDevices( di, DI8DEVCLASS_ALL, find_test_device, &devinst, DIEDFL_ALLDEVICES );
3657 ok( hr == DI_OK, "IDirectInput8_EnumDevices returned: %#x\n", hr );
3658 if (!IsEqualGUID( &devinst.guidProduct, &expect_guid_product ))
3660 win_skip( "device not found, skipping tests\n" );
3661 IDirectInput8_Release( di );
3662 goto done;
3665 check_member( devinst, expect_devinst, "%d", dwSize );
3666 check_member_guid( devinst, expect_devinst, guidProduct );
3667 todo_wine
3668 check_member( devinst, expect_devinst, "%#x", dwDevType );
3669 todo_wine
3670 check_member_wstr( devinst, expect_devinst, tszInstanceName );
3671 todo_wine
3672 check_member_wstr( devinst, expect_devinst, tszProductName );
3673 check_member_guid( devinst, expect_devinst, guidFFDriver );
3674 check_member( devinst, expect_devinst, "%04x", wUsagePage );
3675 check_member( devinst, expect_devinst, "%04x", wUsage );
3677 hr = IDirectInput8_CreateDevice( di, &devinst.guidInstance, NULL, NULL );
3678 ok( hr == E_POINTER, "IDirectInput8_CreateDevice returned %#x\n", hr );
3679 hr = IDirectInput8_CreateDevice( di, NULL, &device, NULL );
3680 ok( hr == E_POINTER, "IDirectInput8_CreateDevice returned %#x\n", hr );
3681 hr = IDirectInput8_CreateDevice( di, &GUID_NULL, &device, NULL );
3682 ok( hr == DIERR_DEVICENOTREG, "IDirectInput8_CreateDevice returned %#x\n", hr );
3683 hr = IDirectInput8_CreateDevice( di, &devinst.guidInstance, &device, NULL );
3684 ok( hr == DI_OK, "IDirectInput8_CreateDevice returned %#x\n", hr );
3686 prop_dword.dwData = 0xdeadbeef;
3687 hr = IDirectInputDevice8_GetProperty( device, DIPROP_VIDPID, &prop_dword.diph );
3688 ok( hr == DI_OK, "IDirectInputDevice8_GetProperty DIPROP_VIDPID returned %#x\n", hr );
3689 /* Wine may get the wrong device here, because the test driver creates another instance of
3690 hidclass.sys, and gets duplicate rawinput handles, which we use in the guidInstance */
3691 todo_wine_if( prop_dword.dwData != EXPECT_VIDPID )
3692 ok( prop_dword.dwData == EXPECT_VIDPID, "got %#x expected %#x\n", prop_dword.dwData, EXPECT_VIDPID );
3694 ref = IDirectInputDevice8_Release( device );
3695 ok( ref == 0, "IDirectInputDeviceW_Release returned %d\n", ref );
3697 hr = IDirectInput8_CreateDevice( di, &expect_guid_product, &device, NULL );
3698 ok( hr == DI_OK, "IDirectInput8_CreateDevice returned %#x\n", hr );
3700 hr = IDirectInputDevice8_GetDeviceInfo( device, NULL );
3701 ok( hr == E_POINTER, "IDirectInputDevice8_GetDeviceInfo returned %#x\n", hr );
3702 devinst.dwSize = sizeof(DIDEVICEINSTANCEW) + 1;
3703 hr = IDirectInputDevice8_GetDeviceInfo( device, &devinst );
3704 ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_GetDeviceInfo returned %#x\n", hr );
3706 devinst.dwSize = sizeof(DIDEVICEINSTANCE_DX3W);
3707 hr = IDirectInputDevice8_GetDeviceInfo( device, &devinst );
3708 ok( hr == DI_OK, "IDirectInputDevice8_GetDeviceInfo returned %#x\n", hr );
3709 todo_wine
3710 check_member_guid( devinst, expect_devinst, guidInstance );
3711 check_member_guid( devinst, expect_devinst, guidProduct );
3712 todo_wine
3713 check_member( devinst, expect_devinst, "%#x", dwDevType );
3714 todo_wine
3715 check_member_wstr( devinst, expect_devinst, tszInstanceName );
3716 todo_wine
3717 check_member_wstr( devinst, expect_devinst, tszProductName );
3719 memset( &devinst, 0, sizeof(devinst) );
3720 devinst.dwSize = sizeof(DIDEVICEINSTANCEW);
3721 hr = IDirectInputDevice8_GetDeviceInfo( device, &devinst );
3722 ok( hr == DI_OK, "IDirectInputDevice8_GetDeviceInfo returned %#x\n", hr );
3723 check_member( devinst, expect_devinst, "%d", dwSize );
3724 todo_wine
3725 check_member_guid( devinst, expect_devinst, guidInstance );
3726 check_member_guid( devinst, expect_devinst, guidProduct );
3727 todo_wine
3728 check_member( devinst, expect_devinst, "%#x", dwDevType );
3729 todo_wine
3730 check_member_wstr( devinst, expect_devinst, tszInstanceName );
3731 todo_wine
3732 check_member_wstr( devinst, expect_devinst, tszProductName );
3733 check_member_guid( devinst, expect_devinst, guidFFDriver );
3734 check_member( devinst, expect_devinst, "%04x", wUsagePage );
3735 check_member( devinst, expect_devinst, "%04x", wUsage );
3737 hr = IDirectInputDevice8_GetCapabilities( device, NULL );
3738 ok( hr == E_POINTER, "IDirectInputDevice8_GetCapabilities returned %#x\n", hr );
3739 hr = IDirectInputDevice8_GetCapabilities( device, &caps );
3740 todo_wine
3741 ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_GetCapabilities returned %#x\n", hr );
3742 caps.dwSize = sizeof(DIDEVCAPS);
3743 hr = IDirectInputDevice8_GetCapabilities( device, &caps );
3744 ok( hr == DI_OK, "IDirectInputDevice8_GetCapabilities returned %#x\n", hr );
3745 check_member( caps, expect_caps, "%d", dwSize );
3746 check_member( caps, expect_caps, "%#x", dwFlags );
3747 todo_wine
3748 check_member( caps, expect_caps, "%#x", dwDevType );
3749 check_member( caps, expect_caps, "%d", dwAxes );
3750 check_member( caps, expect_caps, "%d", dwButtons );
3751 check_member( caps, expect_caps, "%d", dwPOVs );
3752 check_member( caps, expect_caps, "%d", dwFFSamplePeriod );
3753 check_member( caps, expect_caps, "%d", dwFFMinTimeResolution );
3754 check_member( caps, expect_caps, "%d", dwFirmwareRevision );
3755 check_member( caps, expect_caps, "%d", dwHardwareRevision );
3756 check_member( caps, expect_caps, "%d", dwFFDriverVersion );
3758 hr = IDirectInputDevice8_GetProperty( device, NULL, NULL );
3759 ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_GetProperty returned %#x\n", hr );
3760 hr = IDirectInputDevice8_GetProperty( device, &GUID_NULL, NULL );
3761 ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_GetProperty returned %#x\n", hr );
3762 hr = IDirectInputDevice8_GetProperty( device, DIPROP_VIDPID, NULL );
3763 ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_GetProperty returned %#x\n", hr );
3764 hr = IDirectInputDevice8_GetProperty( device, DIPROP_VIDPID, &prop_string.diph );
3765 todo_wine
3766 ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_GetProperty returned %#x\n", hr );
3767 prop_dword.diph.dwHeaderSize = sizeof(DIPROPHEADER) - 1;
3768 hr = IDirectInputDevice8_GetProperty( device, DIPROP_VIDPID, &prop_dword.diph );
3769 todo_wine
3770 ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_GetProperty returned %#x\n", hr );
3771 prop_dword.diph.dwHeaderSize = sizeof(DIPROPHEADER);
3773 prop_dword.dwData = 0xdeadbeef;
3774 hr = IDirectInputDevice8_GetProperty( device, DIPROP_VIDPID, &prop_dword.diph );
3775 ok( hr == DI_OK, "IDirectInputDevice8_GetProperty DIPROP_VIDPID returned %#x\n", hr );
3776 ok( prop_dword.dwData == EXPECT_VIDPID, "got %#x expected %#x\n", prop_dword.dwData, EXPECT_VIDPID );
3778 hr = IDirectInputDevice8_GetProperty( device, DIPROP_GUIDANDPATH, &prop_guid_path.diph );
3779 ok( hr == DI_OK, "IDirectInputDevice8_GetProperty DIPROP_GUIDANDPATH returned %#x\n", hr );
3780 todo_wine
3781 ok( IsEqualGUID( &prop_guid_path.guidClass, &GUID_DEVCLASS_HIDCLASS ), "got guid %s\n",
3782 debugstr_guid( &prop_guid_path.guidClass ) );
3783 todo_wine
3784 ok( !wcsncmp( prop_guid_path.wszPath, expect_path, wcslen( expect_path ) ), "got path %s\n",
3785 debugstr_w(prop_guid_path.wszPath) );
3786 if (!(tmp = wcsrchr( prop_guid_path.wszPath, '&' )))
3787 todo_wine ok( 0, "got path %s\n", debugstr_w(prop_guid_path.wszPath) );
3788 else
3790 ok( !wcscmp( wcsrchr( prop_guid_path.wszPath, '&' ), expect_path_end ), "got path %s\n",
3791 debugstr_w(prop_guid_path.wszPath) );
3794 hr = IDirectInputDevice8_GetProperty( device, DIPROP_INSTANCENAME, &prop_string.diph );
3795 ok( hr == DI_OK, "IDirectInputDevice8_GetProperty DIPROP_INSTANCENAME returned %#x\n", hr );
3796 todo_wine
3797 ok( !wcscmp( prop_string.wsz, expect_devinst.tszInstanceName ), "got instance %s\n",
3798 debugstr_w(prop_string.wsz) );
3799 hr = IDirectInputDevice8_GetProperty( device, DIPROP_PRODUCTNAME, &prop_string.diph );
3800 ok( hr == DI_OK, "IDirectInputDevice8_GetProperty DIPROP_PRODUCTNAME returned %#x\n", hr );
3801 todo_wine
3802 ok( !wcscmp( prop_string.wsz, expect_devinst.tszProductName ), "got product %s\n",
3803 debugstr_w(prop_string.wsz) );
3804 hr = IDirectInputDevice8_GetProperty( device, DIPROP_TYPENAME, &prop_string.diph );
3805 todo_wine
3806 ok( hr == DI_OK, "IDirectInputDevice8_GetProperty DIPROP_TYPENAME returned %#x\n", hr );
3807 todo_wine
3808 ok( !wcscmp( prop_string.wsz, expect_vidpid_str ), "got type %s\n", debugstr_w(prop_string.wsz) );
3809 hr = IDirectInputDevice8_GetProperty( device, DIPROP_USERNAME, &prop_string.diph );
3810 ok( hr == S_FALSE, "IDirectInputDevice8_GetProperty DIPROP_USERNAME returned %#x\n", hr );
3811 todo_wine
3812 ok( !wcscmp( prop_string.wsz, L"" ), "got user %s\n", debugstr_w(prop_string.wsz) );
3814 prop_dword.dwData = 0xdeadbeef;
3815 hr = IDirectInputDevice8_GetProperty( device, DIPROP_JOYSTICKID, &prop_dword.diph );
3816 ok( hr == DI_OK, "IDirectInputDevice8_GetProperty DIPROP_JOYSTICKID returned %#x\n", hr );
3817 todo_wine
3818 ok( prop_dword.dwData == 0, "got %#x expected %#x\n", prop_dword.dwData, 0 );
3820 prop_dword.dwData = 0xdeadbeef;
3821 hr = IDirectInputDevice8_GetProperty( device, DIPROP_AXISMODE, &prop_dword.diph );
3822 todo_wine
3823 ok( hr == DI_OK, "IDirectInputDevice8_GetProperty DIPROP_AXISMODE returned %#x\n", hr );
3824 todo_wine
3825 ok( prop_dword.dwData == DIPROPAXISMODE_ABS, "got %u expected %u\n", prop_dword.dwData, DIPROPAXISMODE_ABS );
3826 prop_dword.dwData = 0xdeadbeef;
3827 hr = IDirectInputDevice8_GetProperty( device, DIPROP_BUFFERSIZE, &prop_dword.diph );
3828 ok( hr == DI_OK, "IDirectInputDevice8_GetProperty DIPROP_BUFFERSIZE returned %#x\n", hr );
3829 ok( prop_dword.dwData == 0, "got %#x expected %#x\n", prop_dword.dwData, 0 );
3830 prop_dword.dwData = 0xdeadbeef;
3831 hr = IDirectInputDevice8_GetProperty( device, DIPROP_FFGAIN, &prop_dword.diph );
3832 todo_wine
3833 ok( hr == DI_OK, "IDirectInputDevice8_GetProperty DIPROP_FFGAIN returned %#x\n", hr );
3834 todo_wine
3835 ok( prop_dword.dwData == 10000, "got %u expected %u\n", prop_dword.dwData, 10000 );
3837 hr = IDirectInputDevice8_GetProperty( device, DIPROP_CALIBRATION, &prop_dword.diph );
3838 ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_GetProperty DIPROP_CALIBRATION returned %#x\n", hr );
3839 hr = IDirectInputDevice8_GetProperty( device, DIPROP_AUTOCENTER, &prop_dword.diph );
3840 todo_wine
3841 ok( hr == DIERR_UNSUPPORTED, "IDirectInputDevice8_GetProperty DIPROP_AUTOCENTER returned %#x\n", hr );
3842 hr = IDirectInputDevice8_GetProperty( device, DIPROP_DEADZONE, &prop_dword.diph );
3843 todo_wine
3844 ok( hr == DIERR_UNSUPPORTED, "IDirectInputDevice8_GetProperty DIPROP_DEADZONE returned %#x\n", hr );
3845 hr = IDirectInputDevice8_GetProperty( device, DIPROP_FFLOAD, &prop_dword.diph );
3846 todo_wine
3847 ok( hr == DIERR_UNSUPPORTED, "IDirectInputDevice8_GetProperty DIPROP_FFLOAD returned %#x\n", hr );
3848 hr = IDirectInputDevice8_GetProperty( device, DIPROP_GRANULARITY, &prop_dword.diph );
3849 todo_wine
3850 ok( hr == DIERR_UNSUPPORTED, "IDirectInputDevice8_GetProperty DIPROP_GRANULARITY returned %#x\n", hr );
3851 hr = IDirectInputDevice8_GetProperty( device, DIPROP_SATURATION, &prop_dword.diph );
3852 todo_wine
3853 ok( hr == DIERR_UNSUPPORTED, "IDirectInputDevice8_GetProperty DIPROP_SATURATION returned %#x\n", hr );
3854 hr = IDirectInputDevice8_GetProperty( device, DIPROP_RANGE, &prop_range.diph );
3855 todo_wine
3856 ok( hr == DIERR_UNSUPPORTED, "IDirectInputDevice8_GetProperty DIPROP_RANGE returned %#x\n", hr );
3858 prop_dword.diph.dwHow = DIPH_BYUSAGE;
3859 prop_dword.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC );
3860 prop_dword.dwData = 0xdeadbeef;
3861 hr = IDirectInputDevice8_GetProperty( device, DIPROP_DEADZONE, &prop_dword.diph );
3862 todo_wine
3863 ok( hr == DI_OK, "IDirectInputDevice8_GetProperty DIPROP_DEADZONE returned %#x\n", hr );
3864 todo_wine
3865 ok( prop_dword.dwData == 0, "got %u expected %u\n", prop_dword.dwData, 0 );
3866 prop_dword.dwData = 0xdeadbeef;
3867 hr = IDirectInputDevice8_GetProperty( device, DIPROP_GRANULARITY, &prop_dword.diph );
3868 todo_wine
3869 ok( hr == DI_OK, "IDirectInputDevice8_GetProperty DIPROP_GRANULARITY returned %#x\n", hr );
3870 todo_wine
3871 ok( prop_dword.dwData == 1, "got %u expected %u\n", prop_dword.dwData, 1 );
3872 prop_dword.dwData = 0xdeadbeef;
3873 hr = IDirectInputDevice8_GetProperty( device, DIPROP_SATURATION, &prop_dword.diph );
3874 todo_wine
3875 ok( hr == DI_OK, "IDirectInputDevice8_GetProperty DIPROP_SATURATION returned %#x\n", hr );
3876 todo_wine
3877 ok( prop_dword.dwData == 10000, "got %u expected %u\n", prop_dword.dwData, 10000 );
3879 prop_range.diph.dwHow = DIPH_BYUSAGE;
3880 prop_range.diph.dwObj = MAKELONG( 0, 0 );
3881 prop_range.lMin = 0xdeadbeef;
3882 prop_range.lMax = 0xdeadbeef;
3883 hr = IDirectInputDevice8_GetProperty( device, DIPROP_RANGE, &prop_range.diph );
3884 todo_wine
3885 ok( hr == DIERR_NOTFOUND, "IDirectInputDevice8_GetProperty DIPROP_RANGE returned %#x\n", hr );
3886 prop_range.diph.dwObj = MAKELONG( 0, HID_USAGE_PAGE_GENERIC );
3887 hr = IDirectInputDevice8_GetProperty( device, DIPROP_RANGE, &prop_range.diph );
3888 todo_wine
3889 ok( hr == DIERR_NOTFOUND, "IDirectInputDevice8_GetProperty DIPROP_RANGE returned %#x\n", hr );
3890 prop_range.diph.dwObj = MAKELONG( HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_X );
3891 hr = IDirectInputDevice8_GetProperty( device, DIPROP_RANGE, &prop_range.diph );
3892 todo_wine
3893 ok( hr == DIERR_NOTFOUND, "IDirectInputDevice8_GetProperty DIPROP_RANGE returned %#x\n", hr );
3894 prop_range.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC );
3895 prop_range.lMin = 0xdeadbeef;
3896 prop_range.lMax = 0xdeadbeef;
3897 hr = IDirectInputDevice8_GetProperty( device, DIPROP_RANGE, &prop_range.diph );
3898 ok( hr == DI_OK, "IDirectInputDevice8_GetProperty DIPROP_RANGE returned %#x\n", hr );
3899 todo_wine
3900 ok( prop_range.lMin == 0, "got %d expected %d\n", prop_range.lMin, 0 );
3901 todo_wine
3902 ok( prop_range.lMax == 65535, "got %d expected %d\n", prop_range.lMax, 65535 );
3904 prop_pointer.diph.dwHow = DIPH_BYUSAGE;
3905 prop_pointer.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC );
3906 hr = IDirectInputDevice8_GetProperty( device, DIPROP_APPDATA, &prop_pointer.diph );
3907 todo_wine
3908 ok( hr == DIERR_NOTINITIALIZED, "IDirectInputDevice8_GetProperty DIPROP_APPDATA returned %#x\n", hr );
3910 hr = IDirectInputDevice8_EnumObjects( device, NULL, NULL, DIDFT_ALL );
3911 ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_EnumObjects returned %#x\n", hr );
3912 hr = IDirectInputDevice8_EnumObjects( device, check_object_count, &res, 0x20 );
3913 todo_wine
3914 ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_EnumObjects returned %#x\n", hr );
3915 res = 0;
3916 hr = IDirectInputDevice8_EnumObjects( device, check_object_count, &res, DIDFT_AXIS | DIDFT_PSHBUTTON );
3917 ok( hr == DI_OK, "IDirectInputDevice8_EnumObjects returned %#x\n", hr );
3918 ok( res == 4, "got %u expected %u\n", res, 4 );
3919 hr = IDirectInputDevice8_EnumObjects( device, check_objects, &check_objects_params, DIDFT_ALL );
3920 ok( hr == DI_OK, "IDirectInputDevice8_EnumObjects returned %#x\n", hr );
3921 ok( check_objects_params.index >= check_objects_params.expect_count, "missing %u objects\n",
3922 check_objects_params.expect_count - check_objects_params.index );
3924 hr = IDirectInputDevice8_SetDataFormat( device, NULL );
3925 ok( hr == E_POINTER, "IDirectInputDevice8_SetDataFormat returned: %#x\n", hr );
3926 hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
3927 ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_SetDataFormat returned: %#x\n", hr );
3928 dataformat.dwSize = sizeof(DIDATAFORMAT);
3929 hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
3930 todo_wine
3931 ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_SetDataFormat returned: %#x\n", hr );
3932 dataformat.dwObjSize = sizeof(DIOBJECTDATAFORMAT);
3933 hr = IDirectInputDevice8_SetDataFormat( device, &dataformat );
3934 ok( hr == DI_OK, "IDirectInputDevice8_SetDataFormat returned: %#x\n", hr );
3935 hr = IDirectInputDevice8_SetDataFormat( device, &c_dfDIJoystick2 );
3936 ok( hr == DI_OK, "IDirectInputDevice8_SetDataFormat returned: %#x\n", hr );
3938 hr = IDirectInputDevice8_SetEventNotification( device, (HANDLE)0xdeadbeef );
3939 todo_wine
3940 ok( hr == E_HANDLE, "IDirectInputDevice8_SetEventNotification returned: %#x\n", hr );
3941 event = CreateEventW( NULL, FALSE, FALSE, NULL );
3942 ok( event != NULL, "CreateEventW failed, last error %u\n", GetLastError() );
3943 hr = IDirectInputDevice8_SetEventNotification( device, event );
3944 ok( hr == DI_OK, "IDirectInputDevice8_SetEventNotification returned: %#x\n", hr );
3946 file = CreateFileW( prop_guid_path.wszPath, FILE_READ_ACCESS | FILE_WRITE_ACCESS,
3947 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
3948 ok( file != INVALID_HANDLE_VALUE, "got error %u\n", GetLastError() );
3950 hr = IDirectInputDevice8_SetCooperativeLevel( device, NULL, 0 );
3951 ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_SetCooperativeLevel returned: %#x\n", hr );
3952 hr = IDirectInputDevice8_SetCooperativeLevel( device, NULL, DISCL_BACKGROUND );
3953 ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_SetCooperativeLevel returned: %#x\n", hr );
3954 hr = IDirectInputDevice8_SetCooperativeLevel( device, NULL, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE );
3955 ok( hr == E_HANDLE, "IDirectInputDevice8_SetCooperativeLevel returned: %#x\n", hr );
3956 hr = IDirectInputDevice8_SetCooperativeLevel( device, NULL, DISCL_BACKGROUND | DISCL_EXCLUSIVE );
3957 ok( hr == E_HANDLE, "IDirectInputDevice8_SetCooperativeLevel returned: %#x\n", hr );
3958 hr = IDirectInputDevice8_SetCooperativeLevel( device, NULL, DISCL_FOREGROUND | DISCL_EXCLUSIVE );
3959 ok( hr == E_HANDLE, "IDirectInputDevice8_SetCooperativeLevel returned: %#x\n", hr );
3961 hwnd = CreateWindowW( L"static", L"dinput", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 10, 10, 200, 200,
3962 NULL, NULL, NULL, NULL );
3964 hr = IDirectInputDevice8_SetCooperativeLevel( device, hwnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE );
3965 ok( hr == DI_OK, "IDirectInputDevice8_SetCooperativeLevel returned: %#x\n", hr );
3966 hr = IDirectInputDevice8_SetCooperativeLevel( device, hwnd, DISCL_BACKGROUND | DISCL_EXCLUSIVE );
3967 ok( hr == DI_OK, "IDirectInputDevice8_SetCooperativeLevel returned: %#x\n", hr );
3968 hr = IDirectInputDevice8_SetCooperativeLevel( device, hwnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE );
3969 ok( hr == DI_OK, "IDirectInputDevice8_SetCooperativeLevel returned: %#x\n", hr );
3971 hr = IDirectInputDevice8_Unacquire( device );
3972 ok( hr == DI_NOEFFECT, "IDirectInputDevice8_Unacquire returned: %#x\n", hr );
3973 hr = IDirectInputDevice8_Acquire( device );
3974 ok( hr == DI_OK, "IDirectInputDevice8_Acquire returned: %#x\n", hr );
3975 hr = IDirectInputDevice8_SetCooperativeLevel( device, hwnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE );
3976 todo_wine
3977 ok( hr == DIERR_ACQUIRED, "IDirectInputDevice8_SetCooperativeLevel returned: %#x\n", hr );
3978 hr = IDirectInputDevice8_Unacquire( device );
3979 ok( hr == DI_OK, "IDirectInputDevice8_Unacquire returned: %#x\n", hr );
3981 DestroyWindow( hwnd );
3983 hr = IDirectInputDevice8_SetCooperativeLevel( device, NULL, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE );
3984 ok( hr == DI_OK, "IDirectInputDevice8_SetCooperativeLevel returned: %#x\n", hr );
3986 hr = IDirectInputDevice8_GetDeviceState( device, sizeof(DIJOYSTATE2), &state );
3987 todo_wine
3988 ok( hr == DIERR_NOTACQUIRED, "IDirectInputDevice8_GetDeviceState returned: %#x\n", hr );
3990 hr = IDirectInputDevice8_Poll( device );
3991 ok( hr == DIERR_NOTACQUIRED, "IDirectInputDevice8_Poll returned: %#x\n", hr );
3993 hr = IDirectInputDevice8_Acquire( device );
3994 ok( hr == DI_OK, "IDirectInputDevice8_Acquire returned: %#x\n", hr );
3996 hr = IDirectInputDevice8_Poll( device );
3997 todo_wine
3998 ok( hr == DI_NOEFFECT, "IDirectInputDevice8_Poll returned: %#x\n", hr );
4000 hr = IDirectInputDevice8_GetDeviceState( device, sizeof(DIJOYSTATE2) + 1, &state );
4001 todo_wine
4002 ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_GetDeviceState returned: %#x\n", hr );
4004 for (i = 0; i < ARRAY_SIZE(injected_input); ++i)
4006 winetest_push_context( "state[%d]", i );
4007 hr = IDirectInputDevice8_GetDeviceState( device, sizeof(DIJOYSTATE2), &state );
4008 ok( hr == DI_OK, "IDirectInputDevice8_GetDeviceState returned: %#x\n", hr );
4009 todo_wine_if( i != 2 )
4010 check_member( state, expect_state[i], "%d", lX );
4011 todo_wine_if( i != 2 )
4012 check_member( state, expect_state[i], "%d", lY );
4013 check_member( state, expect_state[i], "%d", lZ );
4014 todo_wine_if( i == 0 )
4015 check_member( state, expect_state[i], "%#x", rgdwPOV[0] );
4016 check_member( state, expect_state[i], "%#x", rgdwPOV[1] );
4017 check_member( state, expect_state[i], "%#x", rgbButtons[0] );
4018 check_member( state, expect_state[i], "%#x", rgbButtons[1] );
4019 check_member( state, expect_state[i], "%#x", rgbButtons[2] );
4021 send_hid_input( file, &injected_input[i], sizeof(*injected_input) );
4023 res = WaitForSingleObject( event, 100 );
4024 if (i == 0 || i == 3) todo_wine_if( i == 0 )
4025 ok( res == WAIT_TIMEOUT, "WaitForSingleObject succeeded\n" );
4026 else ok( res == WAIT_OBJECT_0, "WaitForSingleObject failed\n" ); ResetEvent( event );
4027 winetest_pop_context();
4030 hr = IDirectInputDevice8_GetDeviceState( device, sizeof(DIJOYSTATE2), &state );
4031 ok( hr == DI_OK, "IDirectInputDevice8_GetDeviceState returned: %#x\n", hr );
4032 winetest_push_context( "state[%d]", i );
4033 todo_wine
4034 check_member( state, expect_state[i], "%d", lX );
4035 todo_wine
4036 check_member( state, expect_state[i], "%d", lY );
4037 check_member( state, expect_state[i], "%d", lZ );
4038 check_member( state, expect_state[i], "%#x", rgdwPOV[0] );
4039 check_member( state, expect_state[i], "%#x", rgdwPOV[1] );
4040 check_member( state, expect_state[i], "%#x", rgbButtons[0] );
4041 check_member( state, expect_state[i], "%#x", rgbButtons[1] );
4042 check_member( state, expect_state[i], "%#x", rgbButtons[2] );
4043 winetest_pop_context();
4045 res = 1;
4046 hr = IDirectInputDevice8_GetDeviceData( device, sizeof(DIDEVICEOBJECTDATA) - 1, objdata, &res, DIGDD_PEEK );
4047 todo_wine
4048 ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_GetDeviceData returned %#x\n", hr );
4049 res = 1;
4050 hr = IDirectInputDevice8_GetDeviceData( device, sizeof(DIDEVICEOBJECTDATA), objdata, &res, DIGDD_PEEK );
4051 ok( hr == DIERR_NOTBUFFERED, "IDirectInputDevice8_GetDeviceData returned %#x\n", hr );
4053 hr = IDirectInputDevice8_Unacquire( device );
4054 ok( hr == DI_OK, "IDirectInputDevice8_Unacquire returned: %#x\n", hr );
4055 prop_dword.diph.dwHow = DIPH_DEVICE;
4056 prop_dword.diph.dwObj = 0;
4057 prop_dword.dwData = 1;
4058 hr = IDirectInputDevice8_SetProperty( device, DIPROP_BUFFERSIZE, &prop_dword.diph );
4059 ok( hr == DI_OK, "IDirectInputDevice8_SetProperty DIPROP_BUFFERSIZE returned %#x\n", hr );
4060 hr = IDirectInputDevice8_Acquire( device );
4061 ok( hr == DI_OK, "IDirectInputDevice8_Unacquire returned: %#x\n", hr );
4063 res = 1;
4064 hr = IDirectInputDevice8_GetDeviceData( device, sizeof(DIDEVICEOBJECTDATA), objdata, &res, DIGDD_PEEK );
4065 ok( hr == DI_OK, "IDirectInputDevice8_GetDeviceData returned %#x\n", hr );
4066 ok( res == 0, "got %u expected %u\n", res, 0 );
4068 send_hid_input( file, &injected_input[0], sizeof(*injected_input) );
4069 res = WaitForSingleObject( event, 100 );
4070 ok( res == WAIT_OBJECT_0, "WaitForSingleObject failed\n" );
4071 ResetEvent( event );
4073 res = 1;
4074 hr = IDirectInputDevice8_GetDeviceData( device, sizeof(DIDEVICEOBJECTDATA), objdata, &res, DIGDD_PEEK );
4075 ok( hr == DI_BUFFEROVERFLOW, "IDirectInputDevice8_GetDeviceData returned %#x\n", hr );
4076 ok( res == 0, "got %u expected %u\n", res, 0 );
4077 res = 1;
4078 hr = IDirectInputDevice8_GetDeviceData( device, sizeof(DIDEVICEOBJECTDATA), objdata, &res, 0 );
4079 todo_wine
4080 ok( hr == DI_OK, "IDirectInputDevice8_GetDeviceData returned %#x\n", hr );
4081 ok( res == 0, "got %u expected %u\n", res, 0 );
4083 hr = IDirectInputDevice8_Unacquire( device );
4084 ok( hr == DI_OK, "IDirectInputDevice8_Unacquire returned: %#x\n", hr );
4085 prop_dword.diph.dwHow = DIPH_DEVICE;
4086 prop_dword.diph.dwObj = 0;
4087 prop_dword.dwData = 10;
4088 hr = IDirectInputDevice8_SetProperty( device, DIPROP_BUFFERSIZE, &prop_dword.diph );
4089 ok( hr == DI_OK, "IDirectInputDevice8_SetProperty DIPROP_BUFFERSIZE returned %#x\n", hr );
4090 hr = IDirectInputDevice8_Acquire( device );
4091 ok( hr == DI_OK, "IDirectInputDevice8_Unacquire returned: %#x\n", hr );
4093 send_hid_input( file, &injected_input[1], sizeof(*injected_input) );
4094 res = WaitForSingleObject( event, 100 );
4095 ok( res == WAIT_OBJECT_0, "WaitForSingleObject failed\n" );
4096 ResetEvent( event );
4098 res = 1;
4099 hr = IDirectInputDevice8_GetDeviceData( device, sizeof(DIDEVICEOBJECTDATA), objdata, &res, DIGDD_PEEK );
4100 ok( hr == DI_OK, "IDirectInputDevice8_GetDeviceData returned %#x\n", hr );
4101 ok( res == 1, "got %u expected %u\n", res, 1 );
4102 check_member( objdata[0], expect_objdata[0], "%#x", dwOfs );
4103 check_member( objdata[0], expect_objdata[0], "%#x", dwData );
4104 todo_wine
4105 check_member( objdata[0], expect_objdata[0], "%#x", dwSequence );
4106 ok( objdata[0].uAppData == -1, "got %p, expected %p\n", (void *)objdata[0].uAppData, (void *)-1 );
4107 res = 4;
4108 hr = IDirectInputDevice8_GetDeviceData( device, sizeof(DIDEVICEOBJECTDATA), objdata, &res, 0 );
4109 ok( hr == DI_OK, "IDirectInputDevice8_GetDeviceData returned %#x\n", hr );
4110 ok( res == 4, "got %u expected %u\n", res, 4 );
4111 for (i = 0; i < 4; ++i)
4113 winetest_push_context( "objdata[%d]", i );
4114 check_member( objdata[i], expect_objdata[1 + i], "%#x", dwOfs );
4115 check_member( objdata[i], expect_objdata[1 + i], "%#x", dwData );
4116 todo_wine
4117 check_member( objdata[i], expect_objdata[1 + i], "%#x", dwSequence );
4118 ok( objdata[i].uAppData == -1, "got %p, expected %p\n", (void *)objdata[i].uAppData, (void *)-1 );
4119 winetest_pop_context();
4122 send_hid_input( file, &injected_input[2], sizeof(*injected_input) );
4123 res = WaitForSingleObject( event, 100 );
4124 ok( res == WAIT_OBJECT_0, "WaitForSingleObject failed\n" );
4125 ResetEvent( event );
4126 send_hid_input( file, &injected_input[4], sizeof(*injected_input) );
4127 res = WaitForSingleObject( event, 100 );
4128 ok( res == WAIT_OBJECT_0, "WaitForSingleObject failed\n" );
4129 ResetEvent( event );
4131 res = 1;
4132 hr = IDirectInputDevice8_GetDeviceData( device, sizeof(DIDEVICEOBJECTDATA), objdata, &res, 0 );
4133 ok( hr == DI_BUFFEROVERFLOW, "IDirectInputDevice8_GetDeviceData returned %#x\n", hr );
4134 ok( res == 1, "got %u expected %u\n", res, 1 );
4135 todo_wine
4136 check_member( objdata[0], expect_objdata[5], "%#x", dwOfs );
4137 todo_wine
4138 check_member( objdata[0], expect_objdata[5], "%#x", dwData );
4139 ok( objdata[0].uAppData == -1, "got %p, expected %p\n", (void *)objdata[0].uAppData, (void *)-1 );
4140 res = ARRAY_SIZE(objdata);
4141 hr = IDirectInputDevice8_GetDeviceData( device, sizeof(DIDEVICEOBJECTDATA), objdata, &res, 0 );
4142 ok( hr == DI_OK, "IDirectInputDevice8_GetDeviceData returned %#x\n", hr );
4143 ok( res == 8, "got %u expected %u\n", res, 8 );
4144 for (i = 0; i < 8; ++i)
4146 winetest_push_context( "objdata[%d]", i );
4147 todo_wine
4148 check_member( objdata[i], expect_objdata[6 + i], "%#x", dwOfs );
4149 todo_wine_if( i != 3 && i != 4 && i != 7 )
4150 check_member( objdata[i], expect_objdata[6 + i], "%#x", dwData );
4151 ok( objdata[i].uAppData == -1, "got %p, expected %p\n", (void *)objdata[i].uAppData, (void *)-1 );
4152 winetest_pop_context();
4155 send_hid_input( file, &injected_input[3], sizeof(*injected_input) );
4156 res = WaitForSingleObject( event, 100 );
4157 ok( res == WAIT_OBJECT_0, "WaitForSingleObject failed\n" );
4158 ResetEvent( event );
4160 hr = IDirectInputDevice8_GetDeviceState( device, sizeof(DIJOYSTATE2), &state );
4161 ok( hr == DI_OK, "IDirectInputDevice8_GetDeviceState returned: %#x\n", hr );
4162 todo_wine
4163 check_member( state, expect_state[3], "%d", lX );
4164 todo_wine
4165 check_member( state, expect_state[3], "%d", lY );
4166 check_member( state, expect_state[3], "%d", lZ );
4167 check_member( state, expect_state[3], "%d", rgdwPOV[0] );
4168 check_member( state, expect_state[3], "%d", rgdwPOV[1] );
4169 check_member( state, expect_state[3], "%#x", rgbButtons[0] );
4170 check_member( state, expect_state[3], "%#x", rgbButtons[1] );
4171 check_member( state, expect_state[3], "%#x", rgbButtons[2] );
4173 prop_range.diph.dwHow = DIPH_DEVICE;
4174 prop_range.diph.dwObj = 0;
4175 prop_range.lMin = 1000;
4176 prop_range.lMax = 51000;
4177 hr = IDirectInputDevice8_SetProperty( device, DIPROP_RANGE, &prop_range.diph );
4178 ok( hr == DI_OK, "IDirectInputDevice8_SetProperty DIPROP_RANGE returned %#x\n", hr );
4179 prop_range.diph.dwHow = DIPH_BYUSAGE;
4180 prop_range.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC );
4181 prop_range.lMin = -4000;
4182 prop_range.lMax = -14000;
4183 hr = IDirectInputDevice8_SetProperty( device, DIPROP_RANGE, &prop_range.diph );
4184 todo_wine
4185 ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_SetProperty DIPROP_RANGE returned %#x\n", hr );
4186 prop_range.lMin = -14000;
4187 prop_range.lMax = -4000;
4188 hr = IDirectInputDevice8_SetProperty( device, DIPROP_RANGE, &prop_range.diph );
4189 ok( hr == DI_OK, "IDirectInputDevice8_SetProperty DIPROP_RANGE returned %#x\n", hr );
4191 prop_range.diph.dwHow = DIPH_DEVICE;
4192 prop_range.diph.dwObj = 0;
4193 prop_range.lMin = 0xdeadbeef;
4194 prop_range.lMax = 0xdeadbeef;
4195 hr = IDirectInputDevice8_GetProperty( device, DIPROP_RANGE, &prop_range.diph );
4196 todo_wine
4197 ok( hr == DIERR_UNSUPPORTED, "IDirectInputDevice8_GetProperty DIPROP_RANGE returned %#x\n", hr );
4198 prop_range.diph.dwHow = DIPH_BYUSAGE;
4199 prop_range.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC );
4200 prop_range.lMin = 0xdeadbeef;
4201 prop_range.lMax = 0xdeadbeef;
4202 hr = IDirectInputDevice8_GetProperty( device, DIPROP_RANGE, &prop_range.diph );
4203 ok( hr == DI_OK, "IDirectInputDevice8_GetProperty DIPROP_RANGE returned %#x\n", hr );
4204 todo_wine
4205 ok( prop_range.lMin == -14000, "got %d expected %d\n", prop_range.lMin, -14000 );
4206 todo_wine
4207 ok( prop_range.lMax == -4000, "got %d expected %d\n", prop_range.lMax, -4000 );
4208 prop_range.diph.dwHow = DIPH_BYUSAGE;
4209 prop_range.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_Y, HID_USAGE_PAGE_GENERIC );
4210 prop_range.lMin = 0xdeadbeef;
4211 prop_range.lMax = 0xdeadbeef;
4212 hr = IDirectInputDevice8_GetProperty( device, DIPROP_RANGE, &prop_range.diph );
4213 ok( hr == DI_OK, "IDirectInputDevice8_GetProperty DIPROP_RANGE returned %#x\n", hr );
4214 todo_wine
4215 ok( prop_range.lMin == 1000, "got %d expected %d\n", prop_range.lMin, 1000 );
4216 todo_wine
4217 ok( prop_range.lMax == 51000, "got %d expected %d\n", prop_range.lMax, 51000 );
4219 hr = IDirectInputDevice8_GetDeviceState( device, sizeof(DIJOYSTATE2), &state );
4220 ok( hr == DI_OK, "IDirectInputDevice8_GetDeviceState returned: %#x\n", hr );
4221 todo_wine
4222 check_member( state, expect_state_abs[1], "%d", lX );
4223 todo_wine
4224 check_member( state, expect_state_abs[1], "%d", lY );
4225 check_member( state, expect_state_abs[1], "%d", lZ );
4226 check_member( state, expect_state_abs[1], "%d", rgdwPOV[0] );
4227 check_member( state, expect_state_abs[1], "%d", rgdwPOV[1] );
4228 check_member( state, expect_state_abs[1], "%#x", rgbButtons[0] );
4229 check_member( state, expect_state_abs[1], "%#x", rgbButtons[1] );
4230 check_member( state, expect_state_abs[1], "%#x", rgbButtons[2] );
4232 hr = IDirectInputDevice8_SetProperty( device, NULL, NULL );
4233 ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_SetProperty returned %#x\n", hr );
4234 hr = IDirectInputDevice8_SetProperty( device, &GUID_NULL, NULL );
4235 ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_SetProperty returned %#x\n", hr );
4236 hr = IDirectInputDevice8_SetProperty( device, DIPROP_VIDPID, NULL );
4237 ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_SetProperty returned %#x\n", hr );
4238 hr = IDirectInputDevice8_SetProperty( device, DIPROP_VIDPID, &prop_string.diph );
4239 todo_wine
4240 ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_SetProperty returned %#x\n", hr );
4242 prop_dword.diph.dwHow = DIPH_DEVICE;
4243 prop_dword.diph.dwObj = 0;
4244 prop_dword.dwData = 0xdeadbeef;
4245 hr = IDirectInputDevice8_SetProperty( device, DIPROP_VIDPID, &prop_dword.diph );
4246 todo_wine
4247 ok( hr == DIERR_READONLY, "IDirectInputDevice8_SetProperty DIPROP_VIDPID returned %#x\n", hr );
4248 hr = IDirectInputDevice8_SetProperty( device, DIPROP_GUIDANDPATH, &prop_guid_path.diph );
4249 todo_wine
4250 ok( hr == DIERR_READONLY, "IDirectInputDevice8_SetProperty DIPROP_GUIDANDPATH returned %#x\n", hr );
4252 prop_string.diph.dwHow = DIPH_DEVICE;
4253 prop_string.diph.dwObj = 0;
4254 wcscpy( prop_string.wsz, L"instance name" );
4255 hr = IDirectInputDevice8_SetProperty( device, DIPROP_INSTANCENAME, &prop_string.diph );
4256 ok( hr == DIERR_UNSUPPORTED, "IDirectInputDevice8_SetProperty DIPROP_INSTANCENAME returned %#x\n", hr );
4258 wcscpy( prop_string.wsz, L"product name" );
4259 hr = IDirectInputDevice8_SetProperty( device, DIPROP_PRODUCTNAME, &prop_string.diph );
4260 todo_wine
4261 ok( hr == DI_OK, "IDirectInputDevice8_SetProperty DIPROP_PRODUCTNAME returned %#x\n", hr );
4262 hr = IDirectInputDevice8_GetProperty( device, DIPROP_PRODUCTNAME, &prop_string.diph );
4263 ok( hr == DI_OK, "IDirectInputDevice8_GetProperty DIPROP_PRODUCTNAME returned %#x\n", hr );
4264 todo_wine
4265 ok( !wcscmp( prop_string.wsz, expect_devinst.tszProductName ), "got product %s\n",
4266 debugstr_w(prop_string.wsz) );
4268 hr = IDirectInputDevice8_SetProperty( device, DIPROP_TYPENAME, &prop_string.diph );
4269 todo_wine
4270 ok( hr == DIERR_READONLY, "IDirectInputDevice8_SetProperty DIPROP_TYPENAME returned %#x\n", hr );
4271 hr = IDirectInputDevice8_SetProperty( device, DIPROP_USERNAME, &prop_string.diph );
4272 todo_wine
4273 ok( hr == DIERR_READONLY, "IDirectInputDevice8_SetProperty DIPROP_USERNAME returned %#x\n", hr );
4274 hr = IDirectInputDevice8_SetProperty( device, DIPROP_FFLOAD, &prop_dword.diph );
4275 todo_wine
4276 ok( hr == DIERR_READONLY, "IDirectInputDevice8_SetProperty DIPROP_FFLOAD returned %#x\n", hr );
4277 hr = IDirectInputDevice8_SetProperty( device, DIPROP_GRANULARITY, &prop_dword.diph );
4278 todo_wine
4279 ok( hr == DIERR_READONLY, "IDirectInputDevice8_SetProperty DIPROP_GRANULARITY returned %#x\n", hr );
4281 hr = IDirectInputDevice8_SetProperty( device, DIPROP_JOYSTICKID, &prop_dword.diph );
4282 todo_wine
4283 ok( hr == DIERR_ACQUIRED, "IDirectInputDevice8_SetProperty DIPROP_JOYSTICKID returned %#x\n", hr );
4284 hr = IDirectInputDevice8_SetProperty( device, DIPROP_AXISMODE, &prop_dword.diph );
4285 ok( hr == DIERR_ACQUIRED, "IDirectInputDevice8_SetProperty DIPROP_AXISMODE returned %#x\n", hr );
4286 hr = IDirectInputDevice8_SetProperty( device, DIPROP_BUFFERSIZE, &prop_dword.diph );
4287 ok( hr == DIERR_ACQUIRED, "IDirectInputDevice8_SetProperty DIPROP_BUFFERSIZE returned %#x\n", hr );
4288 hr = IDirectInputDevice8_SetProperty( device, DIPROP_AUTOCENTER, &prop_dword.diph );
4289 todo_wine
4290 ok( hr == DIERR_ACQUIRED, "IDirectInputDevice8_SetProperty DIPROP_AUTOCENTER returned %#x\n", hr );
4291 prop_pointer.diph.dwHow = DIPH_BYUSAGE;
4292 prop_pointer.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC );
4293 hr = IDirectInputDevice8_SetProperty( device, DIPROP_APPDATA, &prop_pointer.diph );
4294 todo_wine
4295 ok( hr == DIERR_ACQUIRED, "IDirectInputDevice8_SetProperty DIPROP_APPDATA returned %#x\n", hr );
4297 prop_dword.diph.dwHow = DIPH_DEVICE;
4298 prop_dword.diph.dwObj = 0;
4299 prop_dword.dwData = 10001;
4300 hr = IDirectInputDevice8_SetProperty( device, DIPROP_DEADZONE, &prop_dword.diph );
4301 todo_wine
4302 ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_SetProperty DIPROP_DEADZONE returned %#x\n", hr );
4303 hr = IDirectInputDevice8_SetProperty( device, DIPROP_SATURATION, &prop_dword.diph );
4304 todo_wine
4305 ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_SetProperty DIPROP_SATURATION returned %#x\n", hr );
4306 prop_dword.dwData = 1000;
4307 hr = IDirectInputDevice8_SetProperty( device, DIPROP_DEADZONE, &prop_dword.diph );
4308 todo_wine
4309 ok( hr == DI_OK, "IDirectInputDevice8_SetProperty DIPROP_DEADZONE returned %#x\n", hr );
4310 prop_dword.dwData = 6000;
4311 hr = IDirectInputDevice8_SetProperty( device, DIPROP_SATURATION, &prop_dword.diph );
4312 todo_wine
4313 ok( hr == DI_OK, "IDirectInputDevice8_SetProperty DIPROP_SATURATION returned %#x\n", hr );
4315 hr = IDirectInputDevice8_GetProperty( device, DIPROP_DEADZONE, &prop_dword.diph );
4316 todo_wine
4317 ok( hr == DIERR_UNSUPPORTED, "IDirectInputDevice8_GetProperty DIPROP_DEADZONE returned %#x\n", hr );
4318 hr = IDirectInputDevice8_GetProperty( device, DIPROP_SATURATION, &prop_dword.diph );
4319 todo_wine
4320 ok( hr == DIERR_UNSUPPORTED, "IDirectInputDevice8_GetProperty DIPROP_SATURATION returned %#x\n", hr );
4322 prop_dword.diph.dwHow = DIPH_BYUSAGE;
4323 prop_dword.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC );
4324 prop_dword.dwData = 2000;
4325 hr = IDirectInputDevice8_SetProperty( device, DIPROP_DEADZONE, &prop_dword.diph );
4326 todo_wine
4327 ok( hr == DI_OK, "IDirectInputDevice8_SetProperty DIPROP_DEADZONE returned %#x\n", hr );
4328 ok( prop_dword.dwData == 2000, "got %u expected %u\n", prop_dword.dwData, 2000 );
4329 prop_dword.dwData = 7000;
4330 hr = IDirectInputDevice8_SetProperty( device, DIPROP_SATURATION, &prop_dword.diph );
4331 todo_wine
4332 ok( hr == DI_OK, "IDirectInputDevice8_SetProperty DIPROP_SATURATION returned %#x\n", hr );
4334 prop_dword.diph.dwHow = DIPH_BYUSAGE;
4335 prop_dword.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC );
4336 prop_dword.dwData = 0xdeadbeef;
4337 hr = IDirectInputDevice8_GetProperty( device, DIPROP_DEADZONE, &prop_dword.diph );
4338 todo_wine
4339 ok( hr == DI_OK, "IDirectInputDevice8_GetProperty DIPROP_DEADZONE returned %#x\n", hr );
4340 todo_wine
4341 ok( prop_dword.dwData == 2000, "got %u expected %u\n", prop_dword.dwData, 2000 );
4342 prop_dword.dwData = 0xdeadbeef;
4343 hr = IDirectInputDevice8_GetProperty( device, DIPROP_SATURATION, &prop_dword.diph );
4344 todo_wine
4345 ok( hr == DI_OK, "IDirectInputDevice8_GetProperty DIPROP_SATURATION returned %#x\n", hr );
4346 todo_wine
4347 ok( prop_dword.dwData == 7000, "got %u expected %u\n", prop_dword.dwData, 7000 );
4349 prop_dword.diph.dwHow = DIPH_BYUSAGE;
4350 prop_dword.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_Y, HID_USAGE_PAGE_GENERIC );
4351 prop_dword.dwData = 0xdeadbeef;
4352 hr = IDirectInputDevice8_GetProperty( device, DIPROP_DEADZONE, &prop_dword.diph );
4353 todo_wine
4354 ok( hr == DI_OK, "IDirectInputDevice8_GetProperty DIPROP_DEADZONE returned %#x\n", hr );
4355 todo_wine
4356 ok( prop_dword.dwData == 1000, "got %u expected %u\n", prop_dword.dwData, 1000 );
4357 prop_dword.dwData = 0xdeadbeef;
4358 hr = IDirectInputDevice8_GetProperty( device, DIPROP_SATURATION, &prop_dword.diph );
4359 todo_wine
4360 ok( hr == DI_OK, "IDirectInputDevice8_GetProperty DIPROP_SATURATION returned %#x\n", hr );
4361 todo_wine
4362 ok( prop_dword.dwData == 6000, "got %u expected %u\n", prop_dword.dwData, 6000 );
4364 for (i = 0; i < ARRAY_SIZE(injected_input); ++i)
4366 winetest_push_context( "state[%d]", i );
4367 hr = IDirectInputDevice8_GetDeviceState( device, sizeof(DIJOYSTATE2), &state );
4368 ok( hr == DI_OK, "IDirectInputDevice8_GetDeviceState returned: %#x\n", hr );
4369 if (broken( state.lX == -10750 )) win_skip( "Ignoring 32-bit rounding\n" );
4370 else
4372 todo_wine
4373 check_member( state, expect_state_abs[i], "%d", lX );
4374 todo_wine_if( i != 2 )
4375 check_member( state, expect_state_abs[i], "%d", lY );
4377 check_member( state, expect_state_abs[i], "%d", lZ );
4378 check_member( state, expect_state_abs[i], "%d", rgdwPOV[0] );
4379 check_member( state, expect_state_abs[i], "%d", rgdwPOV[1] );
4380 check_member( state, expect_state_abs[i], "%#x", rgbButtons[0] );
4381 check_member( state, expect_state_abs[i], "%#x", rgbButtons[1] );
4382 check_member( state, expect_state_abs[i], "%#x", rgbButtons[2] );
4384 send_hid_input( file, &injected_input[i], sizeof(*injected_input) );
4386 res = WaitForSingleObject( event, 100 );
4387 if (i == 0 || i == 3) todo_wine_if( i == 0 )
4388 ok( res == WAIT_TIMEOUT, "WaitForSingleObject succeeded\n" );
4389 else ok( res == WAIT_OBJECT_0, "WaitForSingleObject failed\n" ); ResetEvent( event );
4390 winetest_pop_context();
4393 hr = IDirectInputDevice8_GetDeviceState( device, sizeof(DIJOYSTATE2), &state );
4394 ok( hr == DI_OK, "IDirectInputDevice8_GetDeviceState returned: %#x\n", hr );
4395 winetest_push_context( "state[%d]", i );
4396 todo_wine
4397 check_member( state, expect_state_abs[i], "%d", lX );
4398 todo_wine
4399 check_member( state, expect_state_abs[i], "%d", lY );
4400 check_member( state, expect_state_abs[i], "%d", lZ );
4401 check_member( state, expect_state_abs[i], "%d", rgdwPOV[0] );
4402 check_member( state, expect_state_abs[i], "%d", rgdwPOV[1] );
4403 check_member( state, expect_state_abs[i], "%#x", rgbButtons[0] );
4404 check_member( state, expect_state_abs[i], "%#x", rgbButtons[1] );
4405 check_member( state, expect_state_abs[i], "%#x", rgbButtons[2] );
4406 winetest_pop_context();
4408 hr = IDirectInputDevice8_Unacquire( device );
4409 ok( hr == DI_OK, "IDirectInputDevice8_Unacquire returned: %#x\n", hr );
4411 prop_dword.diph.dwHow = DIPH_DEVICE;
4412 prop_dword.diph.dwObj = 0;
4413 hr = IDirectInputDevice8_SetProperty( device, DIPROP_JOYSTICKID, &prop_dword.diph );
4414 ok( hr == DIERR_UNSUPPORTED, "IDirectInputDevice8_SetProperty DIPROP_JOYSTICKID returned %#x\n", hr );
4415 prop_dword.dwData = 0x1000;
4416 hr = IDirectInputDevice8_SetProperty( device, DIPROP_BUFFERSIZE, &prop_dword.diph );
4417 ok( hr == DI_OK, "IDirectInputDevice8_SetProperty DIPROP_BUFFERSIZE returned %#x\n", hr );
4418 prop_dword.dwData = 0xdeadbeef;
4419 hr = IDirectInputDevice8_SetProperty( device, DIPROP_AUTOCENTER, &prop_dword.diph );
4420 todo_wine
4421 ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_SetProperty DIPROP_AUTOCENTER returned %#x\n", hr );
4422 prop_dword.dwData = DIPROPAUTOCENTER_ON;
4423 hr = IDirectInputDevice8_SetProperty( device, DIPROP_AUTOCENTER, &prop_dword.diph );
4424 ok( hr == DIERR_UNSUPPORTED, "IDirectInputDevice8_SetProperty DIPROP_AUTOCENTER returned %#x\n", hr );
4425 prop_pointer.diph.dwHow = DIPH_BYUSAGE;
4426 prop_pointer.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC );
4427 prop_pointer.uData = 0xfeedcafe;
4428 hr = IDirectInputDevice8_SetProperty( device, DIPROP_APPDATA, &prop_pointer.diph );
4429 todo_wine
4430 ok( hr == DI_OK, "IDirectInputDevice8_SetProperty DIPROP_APPDATA returned %#x\n", hr );
4432 prop_dword.dwData = 0xdeadbeef;
4433 hr = IDirectInputDevice8_SetProperty( device, DIPROP_AXISMODE, &prop_dword.diph );
4434 todo_wine
4435 ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_SetProperty DIPROP_AXISMODE returned %#x\n", hr );
4436 prop_dword.dwData = DIPROPAXISMODE_REL;
4437 hr = IDirectInputDevice8_SetProperty( device, DIPROP_AXISMODE, &prop_dword.diph );
4438 ok( hr == DI_OK, "IDirectInputDevice8_SetProperty DIPROP_AXISMODE returned %#x\n", hr );
4440 hr = IDirectInputDevice8_Acquire( device );
4441 ok( hr == DI_OK, "IDirectInputDevice8_Unacquire returned: %#x\n", hr );
4443 prop_dword.dwData = 0xdeadbeef;
4444 hr = IDirectInputDevice8_GetProperty( device, DIPROP_AXISMODE, &prop_dword.diph );
4445 todo_wine
4446 ok( hr == DI_OK, "IDirectInputDevice8_GetProperty DIPROP_AXISMODE returned %#x\n", hr );
4447 todo_wine
4448 ok( prop_dword.dwData == DIPROPAXISMODE_REL, "got %u expected %u\n", prop_dword.dwData, DIPROPAXISMODE_REL );
4450 prop_dword.dwData = 0xdeadbeef;
4451 hr = IDirectInputDevice8_GetProperty( device, DIPROP_BUFFERSIZE, &prop_dword.diph );
4452 ok( hr == DI_OK, "IDirectInputDevice8_GetProperty DIPROP_BUFFERSIZE returned %#x\n", hr );
4453 ok( prop_dword.dwData == 0x1000, "got %#x expected %#x\n", prop_dword.dwData, 0x1000 );
4455 prop_pointer.diph.dwHow = DIPH_BYUSAGE;
4456 prop_pointer.diph.dwObj = MAKELONG( HID_USAGE_GENERIC_X, HID_USAGE_PAGE_GENERIC );
4457 hr = IDirectInputDevice8_GetProperty( device, DIPROP_APPDATA, &prop_pointer.diph );
4458 todo_wine
4459 ok( hr == DI_OK, "IDirectInputDevice8_GetProperty DIPROP_APPDATA returned %#x\n", hr );
4460 ok( prop_pointer.uData == 0xfeedcafe, "got %p expected %p\n", (void *)prop_pointer.uData, (void *)0xfeedcafe );
4462 prop_dword.diph.dwHow = DIPH_DEVICE;
4463 prop_dword.diph.dwObj = 0;
4464 prop_dword.dwData = 0xdeadbeef;
4465 hr = IDirectInputDevice8_SetProperty( device, DIPROP_FFGAIN, &prop_dword.diph );
4466 todo_wine
4467 ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_SetProperty DIPROP_FFGAIN returned %#x\n", hr );
4468 prop_dword.dwData = 1000;
4469 hr = IDirectInputDevice8_SetProperty( device, DIPROP_FFGAIN, &prop_dword.diph );
4470 todo_wine
4471 ok( hr == DI_OK, "IDirectInputDevice8_SetProperty DIPROP_FFGAIN returned %#x\n", hr );
4473 prop_dword.dwData = 0xdeadbeef;
4474 hr = IDirectInputDevice8_SetProperty( device, DIPROP_CALIBRATION, &prop_dword.diph );
4475 todo_wine
4476 ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_SetProperty DIPROP_CALIBRATION returned %#x\n", hr );
4477 prop_dword.dwData = 0xdeadbeef;
4478 hr = IDirectInputDevice8_SetProperty( device, DIPROP_DEADZONE, &prop_dword.diph );
4479 todo_wine
4480 ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_SetProperty DIPROP_DEADZONE returned %#x\n", hr );
4481 prop_dword.dwData = 0xdeadbeef;
4482 hr = IDirectInputDevice8_SetProperty( device, DIPROP_SATURATION, &prop_dword.diph );
4483 todo_wine
4484 ok( hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_SetProperty DIPROP_SATURATION returned %#x\n", hr );
4486 for (i = 0; i < ARRAY_SIZE(injected_input); ++i)
4488 winetest_push_context( "state[%d]", i );
4489 hr = IDirectInputDevice8_GetDeviceState( device, sizeof(DIJOYSTATE2), &state );
4490 ok( hr == DI_OK, "IDirectInputDevice8_GetDeviceState returned: %#x\n", hr );
4491 todo_wine
4492 check_member( state, expect_state_rel[i], "%d", lX );
4493 todo_wine
4494 check_member( state, expect_state_rel[i], "%d", lY );
4495 check_member( state, expect_state_rel[i], "%d", lZ );
4496 check_member( state, expect_state_rel[i], "%d", rgdwPOV[0] );
4497 check_member( state, expect_state_rel[i], "%d", rgdwPOV[1] );
4498 check_member( state, expect_state_rel[i], "%#x", rgbButtons[0] );
4499 check_member( state, expect_state_rel[i], "%#x", rgbButtons[1] );
4500 check_member( state, expect_state_rel[i], "%#x", rgbButtons[2] );
4502 send_hid_input( file, &injected_input[i], sizeof(*injected_input) );
4504 res = WaitForSingleObject( event, 100 );
4505 if (i == 3) ok( res == WAIT_TIMEOUT, "WaitForSingleObject succeeded\n" );
4506 else ok( res == WAIT_OBJECT_0, "WaitForSingleObject failed\n" );
4507 ResetEvent( event );
4508 winetest_pop_context();
4511 hr = IDirectInputDevice8_GetDeviceState( device, sizeof(DIJOYSTATE2), &state );
4512 ok( hr == DI_OK, "IDirectInputDevice8_GetDeviceState returned: %#x\n", hr );
4513 winetest_push_context( "state[%d]", i );
4514 todo_wine
4515 check_member( state, expect_state_rel[i], "%d", lX );
4516 todo_wine
4517 check_member( state, expect_state_rel[i], "%d", lY );
4518 check_member( state, expect_state_rel[i], "%d", lZ );
4519 check_member( state, expect_state_rel[i], "%d", rgdwPOV[0] );
4520 check_member( state, expect_state_rel[i], "%d", rgdwPOV[1] );
4521 check_member( state, expect_state_rel[i], "%#x", rgbButtons[0] );
4522 check_member( state, expect_state_rel[i], "%#x", rgbButtons[1] );
4523 check_member( state, expect_state_rel[i], "%#x", rgbButtons[2] );
4524 winetest_pop_context();
4526 hr = IDirectInputDevice8_Unacquire( device );
4527 ok( hr == DI_OK, "IDirectInputDevice8_Unacquire returned: %#x\n", hr );
4529 /* FIXME: we have to wait a bit because Wine DInput internal thread keeps a reference */
4530 Sleep( 100 );
4532 ref = IDirectInputDevice8_Release( device );
4533 ok( ref == 0, "IDirectInputDeviceW_Release returned %d\n", ref );
4535 CloseHandle( event );
4536 CloseHandle( file );
4538 ref = IDirectInput8_Release( di );
4539 ok( ref == 0, "IDirectInput8_Release returned %d\n", ref );
4541 done:
4542 pnp_driver_stop();
4543 cleanup_registry_keys();
4544 SetCurrentDirectoryW( cwd );
4547 START_TEST( hid )
4549 HANDLE mapping;
4550 BOOL is_wow64;
4552 instance = GetModuleHandleW( NULL );
4553 localized = GetUserDefaultLCID() != MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT);
4554 pSignerSign = (void *)GetProcAddress( LoadLibraryW( L"mssign32" ), "SignerSign" );
4556 if (IsWow64Process( GetCurrentProcess(), &is_wow64 ) && is_wow64)
4558 skip( "Running in WoW64.\n" );
4559 return;
4562 mapping = CreateFileMappingW( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(*test_data),
4563 L"Global\\winetest_dinput_section" );
4564 if (!mapping && GetLastError() == ERROR_ACCESS_DENIED)
4566 win_skip( "Failed to create test data mapping.\n" );
4567 return;
4569 ok( !!mapping, "got error %u\n", GetLastError() );
4570 test_data = MapViewOfFile( mapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 1024 );
4571 test_data->running_under_wine = !strcmp( winetest_platform, "wine" );
4572 test_data->winetest_report_success = winetest_report_success;
4573 test_data->winetest_debug = winetest_debug;
4575 okfile = CreateFileW( L"C:\\windows\\winetest_dinput_okfile", GENERIC_READ | GENERIC_WRITE,
4576 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL );
4577 ok( okfile != INVALID_HANDLE_VALUE, "failed to create file, error %u\n", GetLastError() );
4579 subtest( "driver_hid" );
4580 test_hidp_kdr();
4581 test_hid_driver( 0, FALSE );
4582 test_hid_driver( 1, FALSE );
4583 test_hid_driver( 0, TRUE );
4584 test_hid_driver( 1, TRUE );
4586 CoInitialize( NULL );
4587 test_simple_joystick();
4588 CoUninitialize();
4590 UnmapViewOfFile( test_data );
4591 CloseHandle( mapping );
4592 CloseHandle( okfile );
4593 DeleteFileW( L"C:\\windows\\winetest_dinput_okfile" );